From: jk7744.park Date: Sat, 24 Oct 2015 07:50:02 +0000 (+0900) Subject: tizen 2.4 release X-Git-Tag: accepted/tizen/2.4/mobile/20151029.032644^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4cdb77e7e201326ff3f4f947ac991da3096953de;p=framework%2Fmultimedia%2Fgst-rtsp-server.git tizen 2.4 release --- diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..6b672b9 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Wim Taymans +Hyunjun Ko diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..c87cfe8 --- /dev/null +++ b/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/COPYING.LIB b/COPYING.LIB new file mode 100644 index 0000000..c87cfe8 --- /dev/null +++ b/COPYING.LIB @@ -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/ChangeLog b/ChangeLog new file mode 100644 index 0000000..c8c6360 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,7726 @@ +=== release 1.4.5 === + +2014-12-18 Sebastian Dröge + + * configure.ac: + releasing 1.4.5 + +2014-10-31 23:01:53 -0700 Aleix Conchillo Flaqué + + * gst/rtsp-server/rtsp-stream.c: + rtsp-stream: unref srtp decoder when leaving bin + https://bugzilla.gnome.org/show_bug.cgi?id=739481 + +=== release 1.4.4 === + +2014-11-06 13:18:04 +0100 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-rtsp-server.doap: + Release 1.4.4 + +2014-10-29 21:01:39 -0700 Aleix Conchillo Flaqué + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: mikey memory leaks + https://bugzilla.gnome.org/show_bug.cgi?id=739383 + +=== release 1.4.3 === + +2014-09-24 12:51:21 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-rtsp-server.doap: + Release 1.4.3 + +=== release 1.4.2 === + +2014-09-19 15:13:37 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-rtsp-server.doap: + Release 1.4.2 + +2014-09-08 09:26:23 +0200 Srimanta Panda + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + rtsp-media: Make sure that sequence numbers are monotonic after pause + The sequence number is not monotonic for RTP packets after pause. The + reason is basepayloader generates a randon sequence number when the + pipeline goes from ready to pause. With this fix generation of sequence + number will be monotonic when going from pause to play request. + https://bugzilla.gnome.org/show_bug.cgi?id=736017 + +2014-08-28 13:35:15 +0200 Göran Jönsson + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: Protect saved clients watch with a mutex + Fixes a crash when close() is called while merging clients + in handle_tunnel(). In that case close() would destroy the + watch while it is still being used in handle_tunnel(). + https://bugzilla.gnome.org/show_bug.cgi?id=735570 + +=== release 1.4.1 === + +2014-08-27 15:05:07 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-rtsp-server.doap: + Release 1.4.1 + +2014-08-05 16:12:19 +0200 Sebastian Dröge + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + rtsp-media: Query position and stop time only on the RTP parts of the pipeline + The RTCP parts, in specific the RTCP udpsinks, are not flushed when + seeking and will always continue counting the time. This leads to + the NPT after a backwards seek to be something completely different + to the actual seek position. + https://bugzilla.gnome.org/show_bug.cgi?id=732644 + +2014-07-02 22:45:07 +0530 Arun Raghavan + + * gst/rtsp-server/rtsp-media.c: + signals: Fix copy-pasto in target-state signal offset + +=== release 1.4.0 === + +2014-07-19 17:56:31 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-rtsp-server.doap: + Release 1.4.0 + +2014-07-16 20:39:42 +0900 Hyunjun Ko + + * gst/rtsp-server/rtsp-media.h: + media: correct misspelled words in description + https://bugzilla.gnome.org/show_bug.cgi?id=733244 + +=== release 1.3.91 === + +2014-07-11 12:19:08 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-rtsp-server.doap: + Release 1.3.91 + +2014-07-10 17:37:45 +0200 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + docs: update docs + +2014-07-10 17:10:06 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: implement client REMOVE filter + +2014-07-10 17:05:13 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: expose _close() method + Expose a previously internal close method to close the client + connection. + +2014-07-10 12:20:15 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-session-pool.c: + session-pool: signal session-removed outside of the lock + Release the lock before emiting the session-removed signal. + +2014-07-10 11:32:20 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-stream.c: + filter: Release lock in filter functions + Release the object lock before calling the filter functions. We need to + keep a cookie to detect when the list changed during the filter + callback. We also keep a hashtable to make sure we only call the filter + function once for each object in case of concurrent modification. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=732950 + +2014-07-09 15:16:08 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-client.c: + client: check if watch is set in handle_teardown() + The unit tests run without a watch + +2014-07-09 14:19:10 +0200 Ognyan Tonchev + + * tests/check/gst/client.c: + client tests: send teardown to cleanup session + +2014-07-09 14:17:46 +0200 Ognyan Tonchev + + * tests/check/gst/rtspserver.c: + server tests: send teardown to cleanup session + +2014-07-09 15:01:31 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-client.c: + client: keep ref to client for the session removed handler + This extra ref will be dropped when all client sessions have been + removed. A session is removed when a client sends teardown, closes its + endpoint of the TCP connection or the sessions expires. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=732226 + +2014-07-08 12:36:12 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-session.c: + * tests/check/gst/client.c: + client: manage media in session as a last step + Once we manage a media in a session, we can't unmanage it anymore + without destroying it. Therefore, first check everything before we + manage the media, otherwise if something is wrong we have no way to + unmanage the media. + If we created a new session and something went wrong, remove the session + again. Fixes a leak in the unit test. + +2014-07-03 19:52:42 +0100 Tim-Philipp Müller + + * examples/test-mp4.c: + * examples/test-ogg.c: + examples: print 'stream ready at url' for mp4 and ogg example + +2014-07-02 16:04:53 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-sdp.c: + rtsp: fix for MIKEY api change + +2014-07-01 16:12:13 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: free watch context only once + The watch context is freed when the source is destroyed. Avoids + a CRITICAL when we try to unref the context twice. + +2014-07-01 15:02:15 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: fix build + +2014-07-01 14:41:14 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: protect sessions with lock + Protect the list of sessions with the lock. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=732226 + +2014-07-01 12:13:47 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + Client: keep a ref to the session + Don't just keep a weak ref to the session objects but use a hard ref. We + will be notified when a session is removed from the pool (expired) with + the new session-removed signal. + Don't automatically close the RTSP connection when all the sessions of + a client are removed, a client can continue to operate and it can create + a new session if it wants. If you want to remove the client from the + server, you have to use gst_rtsp_server_client_filter() now. + Based on patch from Ognyan Tonchev + See https://bugzilla.gnome.org/show_bug.cgi?id=732226 + +2014-06-30 15:14:34 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + session-pool: add session-removed signal + Add a signal to be notified when a session is removed from the pool. + +2014-06-30 00:37:59 -0700 Evan Nemerson + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-server.h: + Make rtsp-server.h a single-include header, use it for G-I + https://bugzilla.gnome.org/show_bug.cgi?id=732411 + +=== release 1.3.90 === + +2014-06-28 11:48:29 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-rtsp-server.doap: + Release 1.3.90 + +2014-06-27 16:54:22 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: crypto can be NULL + +2014-06-11 16:42:08 -0700 Evan Nemerson + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-mount-points.c: + introspection: add missing allow-none annotations + https://bugzilla.gnome.org/show_bug.cgi?id=730952 + +2014-06-11 16:38:36 -0700 Evan Nemerson + + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-token.c: + introspection: add (nullable) annotations to return values + https://bugzilla.gnome.org/show_bug.cgi?id=730952 + +2014-06-24 09:48:45 +0200 Evan Nemerson + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-stream.c: + gi: improve annotations + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=730953 + +2014-06-24 09:43:44 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-server.c: + signals: use generic marshal function + Use the generic C marshal function. + Use more explicit type instead of G_TYPE_POINTER + +2014-06-24 09:42:47 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-context.h: + context: add type macro + +2014-06-24 09:34:50 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-sdp.h: + sdp: hide key length defines + They don't have a namespace. + +2014-06-22 19:37:31 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.3.3 === + +2014-06-22 19:36:14 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-rtsp-server.doap: + Release 1.3.3 + +2014-05-20 14:48:37 -0700 Aleix Conchillo Flaqué + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-sdp.h: + mikey: add different key length parameters + Add encryption and authentication key length parameters to MIKEY. For + the encoders, the key lengths are obtained from the cipher and auth + algorithms set in the caps. For the decoders, they are obtained while + parsing the key management from the client. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=730472 + +2014-03-16 17:29:48 +0100 Ognyan Tonchev + + * tests/check/gst/stream.c: + stream tests: Make sure we get right multicast address from stream + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=731577 + +2014-06-12 13:49:17 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-client.c: + client: ref the context until rtsp watch is alive + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=731569 + +2014-06-12 13:48:44 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-client.c: + client: Destroy the rtsp watch after connection close + +2014-06-13 16:46:06 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: fix confusing comment + +2014-05-27 12:36:52 +0200 Göran Jönsson + + * gst/rtsp-server/rtsp-session.c: + rtsp-session: Timeout in header. + Adding the possbilty to always have timout in header. + This is configurabe with setting "timeout-always-visible". + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=728264 + +2014-05-21 13:23:40 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.3.2 === + +2014-05-21 13:06:36 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * common: + * configure.ac: + * gst-rtsp-server.doap: + Release 1.3.2 + +2014-05-21 10:54:05 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 211fa5f to 1f5d3c3 + +2014-05-20 15:57:30 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: store TCP ports in transport + Store the TCP ports in the transport when we are doing RTSP over TCP. + This way, we can easily get to the ports from the transport. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=729776 + +2014-05-15 18:15:04 -0700 Aleix Conchillo Flaqué + + * gst/rtsp-server/rtsp-stream.c: + stream: add signals for new RTP/RTCP encoders + New signals to allow the user to configure the dynamically created + encoders. + https://bugzilla.gnome.org/show_bug.cgi?id=730228 + +2014-05-14 09:31:31 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: Make suspend()/unsuspend() virtual + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=730109 + +2014-05-09 17:25:07 -0700 Aleix Conchillo Flaqué + + * gst/rtsp-server/rtsp-client.c: + client: fix send-message signal marshaller + Use generic marshalling for the send-message signal. It has + two POINTER arguments, not just one. + https://bugzilla.gnome.org/show_bug.cgi?id=729900 + +2014-05-09 15:08:48 +0200 Wim Taymans + + * tests/check/gst/media.c: + tests: add and remove pads only once + In this test we simulate a dynamic pad by watching the caps event. + Because of renegotiation in the base payloader now, this caps is sent + multiple times but we can only deal with 1 invocation, use a variable to + only 'add and remove' the pad once. + +2014-05-02 20:06:29 +0100 Tim-Philipp Müller + + * tests/check/gst/rtspserver.c: + tests: add unit test for correct handling of Require headers + https://bugzilla.gnome.org/show_bug.cgi?id=729426 + +2014-05-02 19:59:23 +0100 Tim-Philipp Müller + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: handle Require headers and respond with OPTION_NOT_SUPPORTED + Servers must handle Require headers and must report a failure + if they don't handle any of the Required options, see RFC 2326, + section 12.32: https://tools.ietf.org/html/rfc2326#page-54 + https://bugzilla.gnome.org/show_bug.cgi?id=729426 + +2014-05-03 20:48:43 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.3.1 === + +2014-05-03 18:40:24 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-rtsp-server.doap: + Release 1.3.1 + +2014-05-03 10:18:00 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From bcb1518 to 211fa5f + +2014-05-02 19:58:15 +0100 Tim-Philipp Müller + + * .gitignore: + Update .gitignore + +2014-05-02 19:57:23 +0100 Tim-Philipp Müller + + * tests/check/gst/sessionmedia.c: + tests: fix memory leak in sessionmedia unit test + +2014-05-01 06:17:06 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: emit a signal before sending a message + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=728970 + +2014-05-01 06:07:08 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: pass context to send_message + Pass the current context to send_message, we will need it later. + +2014-05-01 05:29:54 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: fix typo in comment + +2014-04-14 15:17:14 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + media: Do not stop thread twice if default_prepare() fails + +2014-04-15 16:51:17 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: set the watch to flushing before going to NULL + First set the watch to flushing so that we unblock any current and + future attempt to send data on the watch, Then set the pipeline to + NULL. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=728153 + +2014-04-11 23:52:49 +0200 Linus Svensson + + * gst/rtsp-server/rtsp-session-pool.c: + * tests/check/gst/sessionpool.c: + rtsp-session-pool: Fixes annotation + Fixes annotation for gst_rtsp_session_pool_create() and memory leaks + in the sessionpool test. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=728060 + +2014-04-09 16:44:21 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: make media_prepare virtual + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=728029 + +2014-04-12 05:57:00 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + * tests/check/gst/media.c: + media: stop the thread in more error cases + +2014-04-12 05:53:15 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + * tests/check/gst/media.c: + media: allow NULL as the thread + Use the default context whan passing a NULL thread. + +2014-04-10 16:39:11 +0100 Vincent Penquerc'h + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: indent cleanup + Coverity was moaning about unreachable code, and I think it was just + confused by { being before the label. We'll see if it pops up again. + Coverity 1197705 + +2014-04-01 13:04:21 +0200 Göran Jönsson + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + client: Add drop-backlog property + When we have too many messages queued for a client (currently hardcoded + to 100) we overflow and drop the messages. Add a drop-backlog property + to control this behaviour. Setting this property to FALSE will retry + to send the messages to the client by waiting for more room in the + backlog. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=725898 + +2014-04-03 12:19:51 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-client.c: + client: support for POST before GET when setting up a tunnel + +2014-04-02 12:03:32 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-client.c: + client: remove watch of the second client after http tunnel setup + The second client will be freed after the HTTP tunnel has been set up. + Make sure it's RTSP watch is never dispatched again. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=727488 + +2014-03-31 11:00:11 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + * tests/check/gst/media.c: + media: Make media_prepare() fail if port allocation fails + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=727376 + +2014-04-01 16:55:13 +0200 Linus Svensson + + * tests/check/gst/media.c: + media test: cleanup the thread pool in tests + +2014-04-01 13:16:26 +0200 Linus Svensson + + * gst/rtsp-server/rtsp-media.c: + * tests/check/gst/media.c: + rtsp-media: Unblock blocked streams in unprepare + The streams will be blocked when a live media is prepared. + The streams should be unblocked in gst_rtsp_media_unprepare. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=727231 + +2014-04-08 14:49:41 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: release the state lock when going to NULL + Set our state to UNPREPARING and release the state-lock before + setting the pipeline to the NULL state. This way, any pad-added + callback will be able to take the state-lock and check that we are now + unpreparing instead of deadlocking. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=727102 + +2014-04-08 12:08:17 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: protect status with lock + Make sure we only update the status with the lock. + +2014-04-04 17:39:36 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-sdp.c: + rtsp: update for MIKEY API changes + +2014-04-03 12:52:51 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: parse the mikey response from the client + Parse the mikey response from the client and update the policy for + each SSRC. + +2014-04-02 12:36:16 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add method to set crypto info + Make a method to configure the crypto information of a stream. + Set udpsrc in READY instead of PAUSED so that we can configure caps + later. + +2014-04-03 12:57:13 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: cleanup error paths + +2014-04-02 12:27:24 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: fix docs + +2014-03-25 12:42:39 +0100 Wim Taymans + + * examples/test-video.c: + test: enable SRTP only on RTSPS + We only want to enable SRTP when doing rtsp over TLS so that we can + exchange the keys in a secure way. + +2014-03-25 12:41:33 +0100 Wim Taymans + + * examples/test-video.c: + test: print an error on failure + +2014-03-13 17:35:21 +0100 Wim Taymans + + * configure.ac: + * examples/test-video.c: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-stream.c: + * tests/check/Makefile.am: + stream: add SRTP support + Install srtp encoder and decoder elements in rtpbin + Add MIKEY in SDP + +2014-03-16 19:45:26 +0100 Sebastian Rasmussen + + * tests/check/Makefile.am: + * tests/check/gst/sessionpool.c: + tests: Add unit tests for sessionpool + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=726470 + +2014-03-22 13:24:27 +0100 Sebastian Rasmussen + + * tests/check/gst/threadpool.c: + tests: Improve code coverage of rtsp-threadpool tests + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=726873 + +2014-03-23 21:26:00 +0100 Sebastian Rasmussen + + * tests/check/gst/sessionmedia.c: + tests: Improve code coverage for rtsp-session-media + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=726940 + +2014-03-23 21:24:48 +0100 Sebastian Rasmussen + + gobject-introspection: Add annotations to support language bindings + In addition a few cosmetic changes: + * Adjust the order of arguments + * Fix typo: occured -> occurred + * Fix indentation after Return:-clauses + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=726941 + +2014-03-14 19:03:24 +0100 Sebastian Rasmussen + + * gst/rtsp-server/rtsp-stream.c: + rtsp-stream: Don't mix IPv4 and IPv6 addresses + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=726362 + +2014-03-13 14:27:15 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: take caps after the session manager + Take the caps for the SDP after they leave the rtpbin so that we can + also get the properties added by rtpbin elements. + +2014-03-13 14:20:17 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: release lock while pushing out packets + Keep a cache of the transports and use this to iterate the transport + while pushing packets. This allows us to release the lock early. + See https://bugzilla.gnome.org/show_bug.cgi?id=725898 + +2014-03-06 13:52:02 +0100 David Svensson Fors + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + rtsp-client: vmethod for modifying tunnel GET response + Add a vmethod tunnel_http_response where the response to the HTTP GET + for tunneled connections can be modified. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=725879 + +2014-03-03 16:56:53 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-sdp.c: + sdp: make 1 media line per profile + If we have multiple profiles (AVP or AVPF) for a stream, make one m= + line in the SDP for each profile. The client is then supposed to pick + one of the profiles in the SETUP request. Because the m= lines have the + same pt, the client also knows that only 1 option is possible. + +2014-03-03 16:55:48 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + factory: add profile property and pass to media and streams + +2014-03-03 15:12:55 +0100 Wim Taymans + + * examples/test-multicast.c: + * gst/rtsp-server/rtsp-sdp.c: + sdp: pass multicast connection for multicast-only stream + Pass the multicast address of the stream in the connection info in the + SDP so that clients try a multicast connection first. + Only allow multicast connections in the test-multicast example. Also + increase the TTL a little. + +2014-03-02 05:12:01 +0100 Sebastian Rasmussen + + * .gitignore: + .gitignore: Ignore gcov intermediate files + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=725484 + +2014-03-03 12:17:48 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: release some locks in error cases + +2014-03-02 05:12:10 +0100 Sebastian Rasmussen + + docs: Enable and fix gtk-doc warnings + * Makefile: Enable gtk-doc warnings, like the rest of GStreamer + * addresspool/mediafactory: Add missing annotation colon + * stream: Annotate return value + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=725528 + +2014-02-28 09:36:49 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From fe1672e to bcb1518 + +2014-02-26 22:15:51 +0100 Stefan Sauer + + * common: + Automatic update of common submodule + From 1a07da9 to fe1672e + +2014-02-25 15:13:40 +0000 Tim-Philipp Müller + + * examples/Makefile.am: + examples: use LDADD for libs instead of LDFLAGS + +2014-02-25 14:42:09 +0000 Tim-Philipp Müller + + * configure.ac: + configure: make sure releases are in .doap file + +2014-02-25 14:11:00 +0000 Tim-Philipp Müller + + * examples/test-cgroups.c: + examples: test-cgroups: don't put code with side effects into g_assert() + The g_assert() might get compiled out with the right + compiler/preprocessor flags. + +2014-02-25 14:07:50 +0000 Tim-Philipp Müller + + * examples/.gitignore: + examples: add cgroup test binary to .gitignore + +2014-02-25 14:06:47 +0000 Tim-Philipp Müller + + * examples/test-cgroups.c: + examples: fix cgroup test build + Fixes build failure caused by compiler warning: + test-cgroups.c:82:35: error: no previous prototype for ‘gst_rtsp_cgroup_pool_get_type’ [-Werror=missing-prototypes] + +2014-02-21 16:46:45 +0000 Tim-Philipp Müller + + * .gitignore: + .gitignore: ignore temp files created in the course of 'make check' + +2014-02-18 09:44:34 +0100 Branko Subasic + + * gst/rtsp-server/rtsp-media.c: + rtsp-media: don't loose frames handling new PLAY request + If client supplied a range check if the range specifies the start point. + If not, then do an accurate seek to the current position. If a start + point was specified do do a key unit seek to make sure the streaming + starts with decodeable frames. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=724611 + +2014-02-18 16:58:45 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + Revert "media: only flush when setting a new start position" + This reverts commit f67fc23aab59f28796bebf130504ff46ccb97b0a. + We need to do the flush in all cases, demuxer block currently for + non-flushing seeks. + +2014-02-18 16:38:39 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: only flush when setting a new start position + Only flush the pipeline when we change the start position with + a seek. + See https://bugzilla.gnome.org/show_bug.cgi?id=724611 + +2014-02-17 10:43:05 +0100 Göran Jönsson + + * gst/rtsp-server/rtsp-stream.c: + stream: set ttl-mc before adding the socket + Set ttl-mc before adding the socket. Otherwise the value ttl-mc will + never be set on socket. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=724531 + +2014-02-11 14:20:39 -0800 Aleix Conchillo Flaqué + + * gst/rtsp-server/rtsp-media.c: + media: stop thread if media is already prepared + in gst_rtsp_media_prepare() the thread is not used if media is already + prepared (e.g. media shared) so we want to stop the thread. otherwise, a + leak occurs. + https://bugzilla.gnome.org/show_bug.cgi?id=724182 + +2014-02-09 10:52:29 +0100 Sebastian Dröge + + * Makefile.am: + build: Ship gst-rtsp-server.doap file + +2014-02-09 10:47:09 +0100 Sebastian Dröge + + * tests/check/gst/rtspserver.c: + tests: Fix another compiler warning with gcc + +2014-02-09 10:45:28 +0100 Sebastian Dröge + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-mount-points.c: + * gst/rtsp-server/rtsp-stream.c: + * tests/check/gst/client.c: + rtsp-server: Fix lots of compiler warnings with clang + +2014-02-09 10:41:14 +0100 Sebastian Dröge + + * configure.ac: + * gst-rtsp-server.doap: + * tests/Makefile.am: + configure: Synchronise with the configure scripts of the other modules + +2014-02-09 10:25:44 +0100 Sebastian Dröge + + * configure.ac: + configure: Update version to 1.3.0.1 and require GStreamer 1.3.0 + +2014-02-09 10:19:50 +0100 Sebastian Dröge + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-stream.c: + Revert "rtsp-server: support build against last stable release" + This reverts commit 099a10f61f11413ad0ada8ee0b7b7ad1210b1b2f. + Let us require 1.2.3 now, which is going to be released in a few + minutes. + +2014-02-07 16:39:49 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-stream-transport.c: + session: improve RTP-Info + Ignore streams that can't generate RTP-Info instead of failing. + Don't return the empty string when all streams are unconfigured but + return NULL so that we don't generate and empty RTP-Info header. + Improve docs a little. + +2014-02-03 22:41:48 +0200 Andrey Utkin + + * gst/rtsp-server/rtsp-session-media.c: + Don't free rtpinfo GString when it is NULL + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=723554 + +2014-02-06 09:48:05 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: only set keyframe flag when modifying start + Only set the keyframe flag when we modify the start position. The + keyframe flag should probably be ignored when no change is requested but + until we can claim this is all documented properly and all demuxer + implement this, avoid setting the flag. + See also https://bugzilla.gnome.org/show_bug.cgi?id=723075 + +2014-02-06 09:03:50 +0100 Ognyan Tonchev + + * gst/rtsp-server/rtsp-thread-pool.c: + thread-pool: Unref source after mainloop has quit to avoid races in GLib + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=723741 + +2014-02-04 16:27:12 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: handle NULL seqnum and rtptime arguments + +2014-01-31 15:02:22 +0100 Ognyan Tonchev + + * gst/rtsp-server/rtsp-thread-pool.c: + * tests/check/gst/threadpool.c: + thread-pool: Unref reused threads in gst_rtsp_thread_stop() + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=723519 + +2014-02-04 10:14:45 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: add fallback for missing stats property + Use a fallback when the payloader does not have a stats property + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=723554 + +2014-01-30 10:45:56 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From f7bc1c3 to 1a07da9 + +2014-01-28 14:51:26 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: don't leak stats structure + Don't leak the stats structure and deal with NULL stats. + +2014-01-22 22:03:14 +0100 Sebastian Rasmussen + + * gst/rtsp-server/rtsp-stream.c: + stream: Get rtpinfo properties atomically from payloader + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=722844 + +2014-01-21 14:46:47 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: refactor state change functions and signals + Make functions to set the target state and the pipeline state and emit + the signals from those functions. + +2014-01-21 12:01:25 +0100 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add signal to notify of pending state changes + +2014-01-12 16:55:21 +0000 Tim-Philipp Müller + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-stream.c: + rtsp-server: support build against last stable release + Until 1.2.3 is out with the new get_type function and we + can require that. + +2014-01-07 15:28:05 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: fix compilation + +2014-01-07 12:21:09 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add property to configure profiles + +2014-01-07 12:28:47 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: let stream check supported transport + Delegate the check if a transport is allowed to the stream. + See https://bugzilla.gnome.org/show_bug.cgi?id=720696 + +2014-01-07 12:14:15 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add method to check supported transport + Add a method to check if a transport is supported + +2013-12-27 13:11:45 +0100 Sebastian Dröge + + * configure.ac: + configure.ac: Only check for gstreamer-check, not check + We include check in gstreamer-check since quite some time now. + +2013-12-26 17:02:50 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: return clock-rate from get_rtpinfo + And use it to correct the rtptime to the requested start-time. + See https://bugzilla.gnome.org/show_bug.cgi?id=712198 + +2013-12-26 16:28:59 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + session-media: calculate start-time + +2013-12-26 14:43:35 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: also return the running-time + Return the running-time in the rtpinfo as well. + +2013-12-26 15:41:14 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-media.h: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + session-media: let the session-media make the RTPInfo + Add method to create the RTPInfo for a stream-transport. + Add method to create the RTPInfo for all stream-transports in a + session-media. + Use the session-media RTPInfo code in client. This allows us to refactor + another method to link the TCP callbacks. + +2013-12-20 16:39:07 -0800 Aleix Conchillo Flaqué + + mount-points: sort sequence before g_sequence_lookup + * gst/rtsp-server/rtsp-mount-points.c (gst_rtsp_mount_points_remove_factory): + sort sequence if dirty, otherwise lookup will fail. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=720855 + +2013-12-22 23:16:56 +0000 Tim-Philipp Müller + + * configure.ac: + configure: rename package from gst-rtsp to gst-rtsp-server + To match git module name and avoid confusion with the + rtsp lib in gst-plugins-base and rtsp plugin in -good. + +2013-12-22 23:15:02 +0000 Tim-Philipp Müller + + * configure.ac: + configure: bump core/base/good requirement to 1.2.0 + Bump to released stable version and make implicit + requirements explicit. + +2013-12-22 23:04:48 +0000 Tim-Philipp Müller + + * autogen.sh: + * common: + * configure.ac: + Fix broken gettext setup which is not used anyway + +2013-12-22 22:36:06 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From dbedaa0 to d48bed3 + +2013-12-18 16:37:27 +0100 Aleix Conchillo Flaqué + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add setup_sdp vmethod + gst/rtsp-server/rtsp-media.[ch]: added setup_sdp vmethod and public + gst_rtsp_media_setup_sdp. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=720155 + +2013-12-19 14:26:34 +0100 Edward Hervey + + * gst/rtsp-server/rtsp-stream.c: + rtsp-stream: Check return value of sscanf + streamid is only valid if sscanf matched something. + +2013-12-19 14:24:54 +0100 Edward Hervey + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: Fix iteration + Wouldn't even enter the code block otherwise (i++ was used as the check + and not the postfix). + +2013-12-18 15:57:03 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: add vmethod to configure media and streams + Implement a vmethod that can be used to configure the media and the + streams based on the current context. Handle the blocksize handling in + the default handler. + See https://bugzilla.gnome.org/show_bug.cgi?id=720667 + +2013-12-12 00:38:07 +0000 Tim-Philipp Müller + + * .gitignore: + Make git ignore more unit test binaries + +2013-12-12 00:36:07 +0000 Tim-Philipp Müller + + * gst/rtsp-server/rtsp-address-pool.h: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-context.h: + * gst/rtsp-server/rtsp-media-factory-uri.h: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-mount-points.h: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-media.h: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.h: + * gst/rtsp-server/rtsp-stream-transport.h: + * gst/rtsp-server/rtsp-stream.h: + * gst/rtsp-server/rtsp-thread-pool.h: + * gst/rtsp-server/rtsp-token.h: + rtsp-server: add padding to many public structures + Not mini objects though, since they are not subclassable + anyway, nor kept on the stack or inlined in a structure. + +2013-12-03 11:54:42 -0800 Aleix Conchillo Flaqué + + media: add new create_rtpbin vmethod + * gst/rtsp-server/rtsp-media.[ch]: add new create_rtpbin vmethod. + https://bugzilla.gnome.org/show_bug.cgi?id=719734 + +2013-12-03 00:34:52 +0100 Sebastian Rasmussen + + * tests/check/gst/media.c: + tests: fix memory leak, free test's thread pool + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=719733 + +2013-11-29 15:50:52 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream-transport.c: + stream-transport: free url in finalize + +2013-11-29 15:50:23 +0100 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + media: also do state change in suspended state + +2013-11-29 10:53:08 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + media: also handle prepare and range in suspended state + When we are suspended, we are already prepared. + We can get the range in the suspended state. + +2013-11-27 15:04:04 +0100 Branko Subasic + + * tests/check/Makefile.am: + * tests/check/gst/sessionmedia.c: + check: add test for uri in setup + Added unit tests for the new functionality in GstRTSPStreamTransport. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=715168 + +2013-11-28 17:47:18 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: store setup uri and use in PLAY response + Store the uri used when doing the setup and use that in the PLAY + response. + fixes https://bugzilla.gnome.org/show_bug.cgi?id=715168 + +2013-11-28 17:35:45 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + stream-transport: add method to get/set url + +2013-11-28 14:14:35 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: suspend after SDP and unsuspend before PLAYING + Based on patches by Ognyan Tonchev + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=711257 + +2013-11-28 14:10:19 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session.c: + * tests/check/gst/media.c: + * tests/check/gst/mediafactory.c: + media: add suspend modes + Add support for different suspend modes. The stream is suspended right after + producing the SDP and after PAUSE. Different suspend modes are available that + affect the state of the pipeline. NONE leaves the pipeline state unchanged and + is the current and old behaviour, PAUSE will set the pipeline to the PAUSED + state and RESET will bring the pipeline to the NULL state. + A stream is also unsuspended when it goes back to PLAYING, for RESET streams, + this means that the pipeline needs to be prerolled again. + Base on patches by Ognyan Tonchev + See https://bugzilla.gnome.org/show_bug.cgi?id=711257 + +2013-11-28 14:06:53 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: start live streams in blocked state + Start live streams in the blocked state and make them preroll using the + messages. This ensure that no data is played by the sink until we explicitly + unblock the stream right before going to PLAYING. + See https://bugzilla.gnome.org/show_bug.cgi?id=711257 + +2013-11-28 13:58:05 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: refactor starting and waiting for preroll + Based on patches from Ognyan Tonchev + See https://bugzilla.gnome.org/show_bug.cgi?id=711257 + +2013-11-28 13:42:21 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add API to block streams + Add an API to block on the streams and make it post a message. + Based on patch by Ognyan Tonchev + See https://bugzilla.gnome.org/show_bug.cgi?id=711257 + +2013-11-27 15:42:45 +0100 Edward Hervey + + * docs/libs/Makefile.am: + docs: Specify the override file + Even if it's empty (for now) it avoids make distcheck complaining + +2013-11-26 17:23:04 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: move default implementations to where they are used + +2013-11-26 16:25:37 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: take the right lock in gst_rtsp_media_set_pipeline_state() + We need to take the state_lock when calling this method. + +2013-11-26 16:24:35 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: handle add-added on non-bins too + Handle dynamic payloaders that are not bins, as used in the unit-test. + +2013-11-22 01:30:53 +0100 Sebastian Rasmussen + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + rtsp-media/-factory: Fix request pad name comments + These must be escaped for gtk-doc to parse the comments without warnings. + +2013-11-20 15:51:54 -0800 Aleix Conchillo Flaque + + rtsp-media: remove transports if media is in error status + * gst/rtsp-server/rtsp-media.c (gst_rtsp_media_set_state): if we are + trying to change to GST_STATE_NULL and media is in error status, we + remove all transports. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=712776 + +2013-11-22 11:16:20 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + rtsp-media: use element metadata to find payloader + Use the element metadata to find the payloader instead of checking + for the base class. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=712396 + +2013-11-15 12:14:32 -0800 Aleix Conchillo Flaque + + rtsp-stream: add getter for payload type + * gst/rtsp-server/rtsp-stream.c: add new method gst_rtsp_stream_get_pt. + * gst/rtsp-server/rtsp-media.c (pad_added_cb): find real payloader + element and create the stream with this one instead of the dynpay%d + element. + https://bugzilla.gnome.org/show_bug.cgi?id=712396 + +2013-11-22 02:28:28 +0100 Sebastian Rasmussen + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-context.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-mount-points.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-token.c: + rtsp-*: Refer to NULL as a constant in comments + Plus one typo fix. + https://bugzilla.gnome.org/show_bug.cgi?id=714988 + +2013-11-22 03:10:01 +0100 Sebastian Rasmussen + + rtsp-*: Fix type name typos in comments + * rtsp-auth: Refer to GstRTSPToken, not GstRTSPtoken + * rtsp-auth: Refer to part of constant name as text + * rtsp-auth/-permissions/-token: Refer to Permissions not Permission + * rtsp-session-media: Fix GstRTSPSessionMedia typo + * rtsp-stream: Fix typo when refering to GstBin + https://bugzilla.gnome.org/show_bug.cgi?id=714988 + +2013-11-22 00:45:17 +0100 Sebastian Rasmussen + + * docs/README: + * docs/libs/gst-rtsp-server-docs.sgml: + * docs/libs/gst-rtsp-server-sections.txt: + docs: Improve documentation + * Include annotation-glossary to quiet gtk-doc + * Rename remaining ClientState -> Context + * Rename object hierarchy file + * Remove stale chapter references + * Add missing function and object references + * Include missing GstRTSPAddressPoolResult + https://bugzilla.gnome.org/show_bug.cgi?id=714988 + +2013-11-18 10:47:04 +0000 Tim-Philipp Müller + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-stream.c: + rtsp-server: sprinkle some allow-none annotations for g-i + +2013-11-18 11:18:15 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add method to filter transports + Add a method to safely iterate and collect the stream transports + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=711664 + +2013-11-15 16:35:05 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session.c: + rtsp: allow NULL func in filters + Passing a null function make the filters return a list of + refcounted objects. + +2013-11-12 16:52:35 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-address-pool.c: + * tests/check/gst/addresspool.c: + address-pool: fix address increment + Use a guint instead of guint8 to increment the address. It's still not + completely correct because a guint might not be able to hold the complete + address range, but that's an enhacement for later. + Add unit test to test improved behaviour. + https://bugzilla.gnome.org/show_bug.cgi?id=708237 + +2013-11-12 10:55:14 +0100 Patricia Muscalu + + * gst/rtsp-server/rtsp-client.c: + * tests/check/gst/client.c: + client: allow absolute path in requests + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=711689 + +2013-11-07 13:22:09 +0100 Patricia Muscalu + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: make make_path_from_uri a vmethod + +2013-11-12 12:04:55 +0100 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + * tests/check/Makefile.am: + * tests/check/gst/stream.c: + stream: Add functions to get rtp and rtcp sockets + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=710100 + +2013-11-12 11:21:55 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-context.c: + * gst/rtsp-server/rtsp-context.h: + context: defing a GType for the context + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=710018 + +2013-10-12 23:56:00 +0200 Sebastian Pölsterl + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-context.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-mount-points.c: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-stream.c: + Fixed several GIR warnings + +2013-11-12 11:15:46 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + auth: small typos + +2013-10-19 19:25:27 +0200 Sebastian Rasmussen + + * tests/check/Makefile.am: + * tests/check/gst/token.c: + tests: Add unit tests for token + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=710520 + +2013-10-19 19:24:34 +0200 Sebastian Rasmussen + + * gst/rtsp-server/rtsp-token.c: + token: Validate args for gst_rtsp_token_is_allowed + See https://bugzilla.gnome.org/show_bug.cgi?id=710520 + +2013-10-19 19:21:53 +0200 Sebastian Rasmussen + + * gst/rtsp-server/rtsp-token.c: + token: Fix bug when creating empty token + We always want to have a valid GstStructure in the token. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=710520 + +2013-11-12 10:28:55 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-thread-pool.c: + thread-pool: avoid race in shutdown + If we call g_main_loop_quit before the thread has entered g_main_loop_run, we + don't actually stop the mainloop ever. Solve this race by adding an idle source + to the mainloop that calls the _quit. This way we immediately exit the mainloop + if quit was called before we started it. + +2013-10-19 17:36:05 +0200 Sebastian Rasmussen + + * tests/check/Makefile.am: + * tests/check/gst/permissions.c: + tests: Add unit tests for permissions + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=710202 + +2013-10-15 18:50:47 +0200 Sebastian Rasmussen + + * tests/check/gst/mediafactory.c: + tests: Test mediafactory permissions + See https://bugzilla.gnome.org/show_bug.cgi?id=710202 + +2013-10-19 17:39:35 +0200 Sebastian Rasmussen + + * gst/rtsp-server/rtsp-permissions.c: + permissions: Fix refcounting when adding/removing roles + Previously a role that was removed was unreffed twice, and when + replacing an existing role the replaced role was freed while still being + referenced. Both bugs are now fixed. + See https://bugzilla.gnome.org/show_bug.cgi?id=710202 + +2013-10-15 18:01:38 +0200 Sebastian Rasmussen + + * tests/check/gst/media.c: + * tests/check/gst/mediafactory.c: + * tests/check/gst/rtspserver.c: + tests: Check gst_rtsp_url_parse return value + See https://bugzilla.gnome.org/show_bug.cgi?id=710202 + +2013-11-05 11:22:51 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 865aa20 to dbedaa0 + +2013-10-14 12:03:07 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-server.c: + rtsp-server: Fix socket leak + https://bugzilla.gnome.org/show_bug.cgi?id=710088 + +2013-10-30 22:16:54 +0100 Sebastian Dröge + + * gst/rtsp-server/rtsp-session-pool.c: + rtsp-session-pool: Make sure session IDs are properly URI-escaped + https://bugzilla.gnome.org/show_bug.cgi?id=643812 + +2013-10-15 16:37:34 -0700 Aleix Conchillo Flaque + + * examples/.gitignore: + * examples/test-video.c: + examples: fix compilation when WITH_AUTH is defined + https://bugzilla.gnome.org/show_bug.cgi?id=710228 + +2013-10-30 19:10:59 +0100 Sebastian Dröge + + * .gitignore: + gitignore: Add new test binary + +2013-10-09 15:19:12 +0200 Ognyan Tonchev + + * tests/check/Makefile.am: + * tests/check/gst/threadpool.c: + thread-pool: Add unit test for the thread pools + https://bugzilla.gnome.org/show_bug.cgi?id=710228 + +2013-10-09 15:25:10 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-thread-pool.c: + thread-pool: Fix thread leak when reusing threads + https://bugzilla.gnome.org/show_bug.cgi?id=709730 + +2013-10-14 08:30:33 +0200 Patricia Muscalu + + * gst/rtsp-server/rtsp-server.c: + * tests/check/gst/rtspserver.c: + tests: fixed racy behavior in rtspserver tests + https://bugzilla.gnome.org/show_bug.cgi?id=710078 + +2013-10-14 19:36:24 +0200 Sebastian Rasmussen + + * tests/check/gst/addresspool.c: + tests: Improve address pool unit tests + Add a range with mixed IPV4 and IPV6 addresses to pool. + Get an IPV4 address from an IPV6-only pool. + Get an IPV6 address from an IPV4-only pool. + Reserve a IPV6 address from an IPV4-only pool. + Check for unicast addresses in multicast-only pool. + Check for unicast addresses in uni-/multicast-mixed pool. + https://bugzilla.gnome.org/show_bug.cgi?id=710128 + +2013-10-04 06:29:30 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: append query string in PAUSE/PLAY/TEARDOWN as well + +2013-10-01 14:04:17 +0200 Jonas Holmberg + + * gst/rtsp-server/rtsp-client.c: + client: Add query to control path + If the SETUP url contains a query it must be appended to the control + path so that it matches any already created stream in the media. The + query will also be appended to the session media path. + +2013-10-04 05:48:52 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + rtsp-media: remove old line + +2013-10-01 13:15:19 +0200 Jonas Holmberg + + * gst/rtsp-server/rtsp-stream.c: + stream: Correct control comparison + https://bugzilla.gnome.org/show_bug.cgi?id=709176 + +2013-09-09 21:51:44 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-media.c: + media: Check dynamically if the pipeline supports seeking + We should not depend on whether or not the pipeline state change + returned NO_PREROLL or not. A media could dynamically change its + element and switch from seekable to non seekable so it's best to test + the seekable nature of the pipeline dynamically when we try to do a seek. + +2013-09-09 21:51:23 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-media.c: + media: Return FALSE if seeking is not supported + +2013-10-01 17:16:11 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + rtsp-media: don't seek accurate by default + Accurate seeking is perhaps a little overkill in the most common situation and + causes some formats (mp3) over slow media to seek extremely slowly. + +2013-09-26 14:36:58 +0200 Ognyan Tonchev + + * tests/check/gst/rtspserver.c: + tests: fix unit test + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=708742 + +2013-09-26 11:20:05 +0200 Jonas Holmberg + + * gst/rtsp-server/rtsp-client.c: + client: Reply 400 if media cannot be constructed + Reply 400 Bad Request instead of 503 Service Unavailable if media + cannot be constructed in SETUP. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=708821 + +2013-09-26 09:41:10 +0200 Jonas Holmberg + + * gst/rtsp-server/rtsp-client.c: + client: Send setup reply once only + If find_media() failed in handle_setup_request() two replies was sent. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=708819 + +2013-09-24 18:35:36 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 6b03ba7 to 865aa20 + +2013-09-23 14:28:04 +0200 Jonas Holmberg + + * gst/rtsp-server/rtsp-server.c: + server: Emit client-connected signal earlier + Emit client-connected before the client ref is given to a GSource, + otherwise client-connected can be emitted after the client object has + been freed. + +2013-09-24 17:30:18 +0200 Patrick Radizi + + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-address-pool.h: + * gst/rtsp-server/rtsp-stream.c: + * tests/check/gst/addresspool.c: + addresspool: return reason of failure + Let gst_rtsp_address_pool_reserve_address() return the reason why + the address could not be reserved. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=708229 + +2013-09-20 16:47:56 +0200 Edward Hervey + + * autogen.sh: + autogen.sh: Sync behaviour with other GStreamer modules + Allows building from outside of tree amongst other things + +2013-09-20 16:18:54 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From b613661 to 6b03ba7 + +2013-09-19 18:46:14 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 74a6857 to b613661 + +2013-09-19 17:39:24 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 01a7a46 to 74a6857 + +2013-09-19 15:44:26 +0200 Jonas Holmberg + + * gst/rtsp-server/rtsp-client.c: + client: Do not read beyond end of path string + If the setup was done without a control url, make sure we don't try to read the + non-existing control string and crash. + +2013-09-17 14:39:44 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: Fix RTPInfo header + Refactor the method to make the content_base. + Use the content-base and the control url to construct the RTPInfo + url. + +2013-09-17 12:21:02 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: map url to path only in describe + Only map the request url to a path in the DESCRIBE method. The SDP then + contains the base and control urls that should be used to SETUP/PAUSE/ + PLAY/TEARDOWN the media. + +2013-09-17 11:41:57 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + Revert "client: map URL to path in requests" + This reverts commit e3fded2cec897a2ec003450607b916cc1601fd2d. + This is not correct, we only remap the URL to a path in DESCRIBE, the SDP then + contains the base and control urls which are used in the SETUP, PLAY, + PAUSE and TEARDOWN requests. + +2013-09-16 17:16:49 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: map URL to path in requests + +2013-09-16 16:47:40 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-mount-points.c: + * gst/rtsp-server/rtsp-mount-points.h: + mount-points: make vmethod to make path from uri + Make a vmethod to transform an url into a path. The path is then used to lookup + the factory. This makes it possible to also use other bits of the url, such as + the query parameters, to locate the factory. + +2013-09-09 11:05:26 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-thread-pool.c: + * gst/rtsp-server/rtsp-thread-pool.h: + thread-pool: Add cleanup to wait for the threadpool to finish + Also fix race condition if two threads are asking for the first + thread from the thread pool at once. This would case two internal + GThreadPools to be created. + https://bugzilla.gnome.org/show_bug.cgi?id=707753 + +2013-09-05 08:56:02 +0200 Jonas Holmberg + + * gst/rtsp-server/rtsp-client.c: + * tests/check/gst/client.c: + client: free threadpool + https://bugzilla.gnome.org/show_bug.cgi?id=707638 + +2013-09-06 17:23:20 +0200 Jonas Holmberg + + * tests/check/gst/mountpoints.c: + mountpoints tests: unref matched factories + https://bugzilla.gnome.org/show_bug.cgi?id=707638 + +2013-09-05 18:01:18 +0200 Jonas Holmberg + + * tests/check/gst/media.c: + media tests: unref thread pool and caps + https://bugzilla.gnome.org/show_bug.cgi?id=707638 + +2013-09-05 08:53:55 +0200 Jonas Holmberg + + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media.c: + auth, media, media-factory: unref permissions + https://bugzilla.gnome.org/show_bug.cgi?id=707638 + +2013-08-23 15:15:12 +0200 Wim Taymans + + * examples/Makefile.am: + Makefile: add rule for appsrc example + +2013-08-23 15:14:29 +0200 Wim Taymans + + * examples/test-appsrc.c: + tests: add appsrc example + Add an example on how to use appsrc to feed the server pipeline with data. + +2013-08-22 12:10:39 +0200 Patricia Muscalu + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: remove query part from content-base string + Make sure that after the control url has been resolved, it's + not a part of the query-string. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=706568 + +2013-08-23 10:38:43 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: don't check url in response + There is no url or method in the response to check + +2013-08-08 10:57:42 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + Add handle-response signal for when we receive a GET_PARAMETER response + +2013-08-16 12:42:22 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-server.c: + Fix gst_rtsp_server_client_filter, using wrong variable type + +2013-08-22 18:39:59 +0100 Tim-Philipp Müller + + * gst/rtsp-server/rtsp-media-factory-uri.c: + rtsp-media-factory-uri: check AAC properly for whether it's parsed or not + For AAC we need to check for framed=true instead of parsed=true. + https://bugzilla.gnome.org/show_bug.cgi?id=701384 + +2013-08-16 17:05:24 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: optimize pipeline for protocols + When TCP is not an allowed protocol for the stream, avoid creating the + appsrc/appsink/queue and tee elements. + +2013-08-16 16:34:56 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: set protocols on streams + +2013-08-16 16:16:31 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: use protocols supported by stream + +2013-08-16 16:16:00 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-stream.c: + media-factory: allow all protocols + +2013-08-16 16:10:43 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: configure protocols in new streams + +2013-08-16 16:08:43 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add protocols property + +2013-08-05 10:46:33 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-media.c: + rtsp-media: send state in "new-state" signal + https://bugzilla.gnome.org/show_bug.cgi?id=705110 + +2013-08-02 14:11:01 +0200 Lubosz Sarnecki + + * configure.ac: + build: add subdir-objects to AM_INIT_AUTOMAKE + Fixes warnings with automake 1.14 + https://bugzilla.gnome.org/show_bug.cgi?id=705350 + +2013-08-02 17:15:09 +0200 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + server: add method to iterate clients of server + +2013-06-11 19:10:01 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + Add vmethod for rtsp-media subclass to access rtpbin + +2013-07-11 16:12:04 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-client.h: + small documentation fix + +2013-07-11 16:11:55 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-client.c: + Do not take range header if range is invalid + +2013-08-02 16:57:26 +0200 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-media.c: + media: add docs for new method + +2013-07-02 18:55:28 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + Add API to rtsp-media set the pipeline's state + +2013-06-11 19:09:42 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-media.c: + Update current position/duration when gst_rtsp_media_get_range_string is called + +2013-07-22 17:27:27 +0200 Wim Taymans + + * examples/test-cgroups.c: + tests: add some more docs + +2013-07-22 14:25:04 +0200 Wim Taymans + + * examples/test-cgroups.c: + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-context.c: + * gst/rtsp-server/rtsp-context.h: + * gst/rtsp-server/rtsp-params.c: + * gst/rtsp-server/rtsp-params.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-thread-pool.c: + * gst/rtsp-server/rtsp-thread-pool.h: + * tests/check/gst/client.c: + ClientState -> Context + Rename the clientstate to context and put the code in a separate file. + +2013-07-18 12:19:25 +0200 Wim Taymans + + * examples/test-auth.c: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + auth: add support for default token + The default token is used when the user is not authenticated and can be used to + give minimal permissions. + +2013-07-18 11:44:50 +0200 Wim Taymans + + * examples/test-auth.c: + * gst/rtsp-server/rtsp-auth.c: + auth: use defines when possible + +2013-07-18 11:44:21 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-address-pool.c: + address-pool: improve docs + +2013-07-18 12:26:45 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-permissions.c: + permissions: add the role to the copy + +2013-07-17 19:35:33 -0400 Olivier Crête + + * gst/rtsp-server/rtsp-permissions.c: + permissions: Also copy the roles + +2013-07-17 19:32:09 -0400 Olivier Crête + + * gst/rtsp-server/rtsp-permissions.c: + permissions: Make it build + +2013-07-16 12:36:56 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-address-pool.h: + docs: small fixes + +2013-07-16 12:32:51 +0200 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + * gst/rtsp-server/rtsp-stream.c: + * tests/check/gst/client.c: + docs: improve docs + +2013-07-16 12:32:00 +0200 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-address-pool.h: + * tests/check/gst/addresspool.c: + * tests/check/gst/rtspserver.c: + address-pool: cleanups + Remove redundant method, improve docs. + +2013-07-15 17:31:35 +0200 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-permissions.c: + * gst/rtsp-server/rtsp-permissions.h: + * gst/rtsp-server/rtsp-token.c: + docs: improve docs + +2013-07-15 17:12:57 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-permissions.c: + permissions: implement _remove_role + +2013-07-15 17:12:43 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-permissions.c: + permissions: update docs + +2013-07-15 16:48:37 +0200 Wim Taymans + + * tests/check/gst/client.c: + tests: simplify tests + Client settings are now disabled by default so we don't need an auth + module to disable them. + +2013-07-15 16:47:07 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + auth: add default authorizations + When no auth module is specified, use our table of defaults to look up the + default value of the check instead of always allowing everything. This was + we can disallow client settings by default. + +2013-07-15 16:05:02 +0200 Wim Taymans + + * docs/README: + README: update readme + +2013-07-15 15:25:00 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-thread-pool.c: + * gst/rtsp-server/rtsp-thread-pool.h: + thread-pool: add more docs + +2013-07-15 14:50:38 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-thread-pool.c: + * gst/rtsp-server/rtsp-thread-pool.h: + thread-pool: fix race in thread reuse + If we try to reuse a thread right after we made it stop, we end up using a + stopped thread. Catch this case and only reuse threads that are not stopping. + +2013-07-15 14:50:26 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: add small debug + +2013-07-15 11:58:58 +0200 Wim Taymans + + * tests/check/gst/client.c: + client: fix test + Add some permissions to media so we can use the auth and enable + client settings. + +2013-07-15 11:57:49 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: support pushed context in handle_request + If we already have a pushed state, reuse it and add our own things. This makes + it easier to write tests. + +2013-07-15 11:56:06 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + auth: don't auth on methods + Don't authorize on methods anymore but on the resources that we + try to access, this is more flexible. + Move the authorization checks to where they are needed and let the + check return the response on error. + +2013-07-15 11:51:34 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-mount-points.c: + mount-points: add some debug + +2013-07-12 17:26:55 +0200 Wim Taymans + + * tests/check/gst/client.c: + tests: almost fix test + +2013-07-12 17:07:53 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + auth: let the auth module check client_settings + Let the auth module decide if client settings are allowed for the + current client. + +2013-07-12 17:06:37 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-token.c: + * gst/rtsp-server/rtsp-token.h: + token: add method to check boolean permission + +2013-07-12 16:36:05 +0200 Wim Taymans + + * examples/test-auth.c: + * examples/test-cgroups.c: + * gst/rtsp-server/rtsp-token.c: + * gst/rtsp-server/rtsp-token.h: + token: simplify token constructor + Use variable arguments to make easier API. + +2013-07-12 16:17:57 +0200 Wim Taymans + + * examples/test-auth.c: + * examples/test-cgroups.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: add convenience API for factory + +2013-07-12 16:03:07 +0200 Wim Taymans + + * examples/test-auth.c: + * examples/test-cgroups.c: + * gst/rtsp-server/rtsp-permissions.c: + * gst/rtsp-server/rtsp-permissions.h: + permissions: simplify API a little + Avoid passing GstStructure in the add_role method, use varargs instead + to construct the structure behind the scenes. We can then also use the + structure name as the role and simplify some more logic. + +2013-07-12 16:01:14 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + auth: fix typo + +2013-07-12 15:19:29 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + auth: handle unauthorized response + Move handling of the unauthorized response to the auth module, it can add + the appropriate headers to request authorization for the required method + much better than the client. + +2013-07-12 15:13:48 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: allow for sending any message, not only requests + Change the _send_request() method to _send_message() so that we + can both send requests and replies. + +2013-07-12 14:10:13 +0200 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-server.h: + docs: fix docs + +2013-07-12 12:41:52 +0200 Wim Taymans + + * examples/test-video.c: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + auth: move TLS handling to auth module + Remove the TLS settings on the server and move it to the auth module because + that is where security related bits go. + +2013-07-12 12:38:54 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: add state push/pop + +2013-07-12 12:36:40 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: add connection to state + +2013-07-11 20:45:11 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-mount-points.c: + mount-points: fix debug + +2013-07-11 17:28:17 +0200 Wim Taymans + + * tests/check/gst/media.c: + tests: fix media test + +2013-07-11 17:28:04 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-thread-pool.c: + thread-pool: we don't require a state + +2013-07-11 17:18:58 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: let context ref the server + So that we don't risk losing the server object early anc crash. + +2013-07-11 17:05:00 +0200 Wim Taymans + + * tests/check/gst/client.c: + tests: fix client test + +2013-07-11 16:57:14 +0200 Wim Taymans + + * docs/README: + * docs/libs/gst-rtsp-server-docs.sgml: + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-mount-points.c: + * gst/rtsp-server/rtsp-params.c: + * gst/rtsp-server/rtsp-permissions.c: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-thread-pool.c: + * gst/rtsp-server/rtsp-token.c: + docs: improve docs + +2013-07-11 16:28:09 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + session-pool: make vmethod to create a session + Make a vmethod to create a sessions so that subclasses can create + custom session objects + +2013-07-11 12:24:33 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-mount-points.h: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-stream.h: + docs: more updates + +2013-07-11 12:18:26 +0200 Wim Taymans + + * docs/libs/gst-rtsp-server-docs.sgml: + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-address-pool.h: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-permissions.c: + * gst/rtsp-server/rtsp-permissions.h: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-media.h: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.h: + * gst/rtsp-server/rtsp-stream-transport.h: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-thread-pool.h: + docs: update docs + +2013-07-11 10:28:06 +0200 Wim Taymans + + * configure.ac: + * examples/Makefile.am: + configure: compile cgroup example conditionally + Only compile the cgroup example when we have libcgroup + +2013-07-10 20:57:12 +0200 Wim Taymans + + * configure.ac: + * examples/Makefile.am: + * examples/test-cgroups.c: + examples: add cgroups example + +2013-07-10 20:55:03 +0200 Wim Taymans + + * tests/check/gst/rtspserver.c: + tests: fix compilation + +2013-07-10 20:48:47 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-thread-pool.c: + thread-pool: fix vmethod invocation + +2013-07-10 20:48:18 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-thread-pool.c: + * gst/rtsp-server/rtsp-thread-pool.h: + thread-pool: store thread type in thread + +2013-07-10 17:09:27 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: pass thread from pool to media _prepare + Get a thread from the configured threadpool and pass it to the prepare method of + the media. + +2013-07-10 17:08:14 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: Accept a thread in _prepare + Remove out own threadpool handling and use the provided thread and + maincontext for the bus messages and the state changes. + +2013-07-10 17:07:13 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: configure client thread pool + +2013-07-10 17:06:36 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: add method to configure thread pool + +2013-07-10 16:49:55 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + server: use thread pool + Use the thread pool instead of doing our own thing. + +2013-07-10 16:47:43 +0200 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-thread-pool.c: + * gst/rtsp-server/rtsp-thread-pool.h: + thread-pool: add object to manage threads + Add an object to manage the client and media threads. + +2013-07-10 15:28:35 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + auth: debug authorization check + +2013-07-09 20:44:51 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: start media pipeline in context + Start the media pipeline in the provided context (or our default one + when NULL). This makes sure that we run the bus thread in this context and that + all media threads are children of this context. + +2013-07-09 16:38:39 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + factory: pass permissions to media by default + +2013-07-09 16:09:07 +0200 Wim Taymans + + * examples/test-auth.c: + test: add permissions to auth test + Ass some permissions to the media factory in the test. + +2013-07-09 16:04:35 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + auth: simplify auth checks + Remove client from methods, it's now in the state + Perform the check specified by the string, use the information from the + thread local context. + +2013-07-09 16:01:29 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: add state to current thread + Add the client to the ClientState object. + Place the ClientState on the current thread. + +2013-07-09 14:33:43 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: make it possible to set permissions + Make it possible to set permissions on media and media factory objects + +2013-07-09 14:31:15 +0200 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-permissions.c: + * gst/rtsp-server/rtsp-permissions.h: + permissions: add permissions object + Add a mini object to store permissions based on a role. + +2013-07-08 16:29:01 +0200 Wim Taymans + + * examples/test-auth.c: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + auth: add auth checks + Add an enum with auth checks and implement the checks in the auth object. + Perform the checks from the client. + +2013-07-05 20:48:18 +0200 Wim Taymans + + * examples/test-auth.c: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.h: + auth: use the token after authentication + After we authenticated a user, keep the Token around in the state. + +2013-07-05 20:43:39 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * tests/check/gst/media.c: + media: add optional context for bus messages + Add an optional mainloop to _prepare that will handle the bus messages instead + of always using the shared mainloop. + +2013-07-05 20:34:40 +0200 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-token.c: + * gst/rtsp-server/rtsp-token.h: + token: add authorization token + Add a simply miniobject that contains the authorizations. The object contains a + GstStructure that hold all authorization fields. When a user is authenticated, + the auth module will create a Token for the user. The token is then used to + check what operations the user is allowed to do and various other configuration + values. + +2013-07-05 12:08:36 +0200 Wim Taymans + + * examples/test-auth.c: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + auth: remove auth from media and factory + Remove the auth object from media and factory. We want to have the RTSPClient + authenticate and authorize resources, there is no need to place another auth + manager on the media/factory. + +2013-07-04 14:33:59 +0200 Wim Taymans + + * examples/test-auth.c: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.h: + auth: add support for multiple basic auth tokens + Make it possible to add multiple basic authorisation tokens to one authorization + object. Associate with each token an authorization group that will define what + capabilities are allowed. + +2013-07-03 16:15:04 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: error out on non-aggregate control + We require aggregate control (for now) for PLAY, PAUSE and TEARDOWN. + +2013-07-03 15:55:38 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: rework setup request a little + Cache the media in DESCRIBE based on the longest matching path with the uri + that we can find in the mount points. + Rework the setup request a little to get the media from the session or from + the longest matching path, this way we can derive the control string as + everything after the path instead of hardcoding it. + Find the stream based on the control string and only open a session when all + this can be done. + +2013-07-03 15:14:39 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add method to find a stream by control url + +2013-07-03 15:13:45 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add method to check control url of stream + +2013-07-03 12:37:48 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-media.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + session: use path matching for session media + Use a path string instead of a uri to lookup session media in the sessions. Also + use path matching to find the largest possible path that matches. + +2013-07-03 11:04:53 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-mount-points.c: + * gst/rtsp-server/rtsp-mount-points.h: + * tests/check/gst/mountpoints.c: + mount-points: remove useless vmethod + Making lookups in the mount points should not be done with a URL, if there is a + mapping to be done from URL to mount points, we'll need to do it somewhere + else. + +2013-07-03 10:25:46 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-mount-points.c: + * gst/rtsp-server/rtsp-mount-points.h: + * tests/check/gst/mountpoints.c: + mount-points: improve mount point searching + Use a GSequence to keep track of the mount points. + Match a URL to the longest matching registered mount point. This should be the + URL to perform aggreagate control and the remainder is the stream specific + control part. + Add some unit tests for this. + +2013-07-03 10:40:33 +0200 Sebastian Dröge + + * gst/rtsp-server/Makefile.am: + rtsp-server: Allow building of static library + +2013-07-02 15:59:16 +0200 Wim Taymans + + * tests/check/gst/mediafactory.c: + tests: fix compilation + +2013-07-02 15:54:43 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-sdp.c: + sdp: get control string from stream + Use the control string as configured in the stream. + +2013-07-02 14:44:35 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add methods and property to set control string + +2013-07-02 11:58:02 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: cleanups + Rename variables for clarity + Keep media in state when we can + +2013-07-01 16:46:07 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add more support for IPv6 + Rename _get_address to _get_multicast_address in GstRTSPStream to + make it clear that this function only deals with multicast. + Make it possible to have both an IPv4 and IPv6 multicast address on + a stream. Give the client an IPv4 or IPv6 address depending on the + address it used to connect to the server. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=702002 + +2013-07-01 15:18:43 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: fix comment + +2013-07-01 14:45:49 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: handle failed port allocation + Allow for ipv4 or ipv6 socket allocations to fail. Only report failure if we + can't allocate any family at all. Also keep track of what port families we + allocated. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=703175 + +2013-07-01 12:20:50 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: improve docs + +2013-07-01 12:04:45 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream-transport.c: + stream-transport: remove old if 0 block + +2013-06-27 11:21:42 +0200 Patricia Muscalu + + * tests/check/gst/client.c: + tests: fix tests + gst_rtsp_client_get_uri() has been removed + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=703173 + +2013-06-26 17:18:33 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: add method to filter managed sessions + Add a method to filter the sessions managed by this client connection. + See https://bugzilla.gnome.org/show_bug.cgi?id=703016 + +2013-06-26 16:32:06 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: remove _get_uri() method + Remove the get_uri() method on the client. A client has no uri, the uri + property is an internal property to manage the last cached media for + the client. + +2013-06-26 16:31:39 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: fix typo + +2013-06-26 14:42:15 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + rtsp-media: Do not leak the query in default_query_stop + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=703120 + +2013-06-25 15:46:41 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: don't unlock when conversion fails + Don't unlock the state lock when conversion fails because it was not locked. + +2013-06-10 17:32:40 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + Add query_position and query_stop vmethods to rtsp-media + +2013-06-10 17:33:01 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-media.c: + Fix typo in property install for rtsp-media's time-provider + +2013-06-25 15:09:13 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: clean some variables + Clean some variables and add some guards to _send_request() + +2013-06-10 17:32:12 -0400 Youness Alaoui + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + Add gst_rtsp_client_send_request API + This makes it possible to send arbitrary messages to a client, such as + SET_PARAMETER or GET_PARAMETER + +2013-06-24 23:56:57 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add _get_element() method + Add method to get the element used when creating the media. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=703008 + +2013-06-24 23:51:38 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: fix docs + +2013-06-24 11:41:27 -0700 Aleix Conchillo Flaque + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: allow access to the rtp session + https://bugzilla.gnome.org/show_bug.cgi?id=703004 + +2013-06-24 10:43:59 +0200 Alexander Schrab + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + dscp qos support in gst-rtsp-stream + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=702645 + +2013-06-20 17:30:49 +0200 Wim Taymans + + * tests/check/gst/rtspserver.c: + tests: fix test + Actually do what the comment says. Also keep the old code around, not sure what + should happen when you get a 454 from a TEARDOWN, does it close the connection? + it currently doesn't. + +2013-06-20 12:20:21 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: also watch newly created session + When we newly created a session, start watching it immediately instead of + on the next request. + +2013-06-20 12:18:23 +0200 Patricia Muscalu + + * tests/check/gst/client.c: + tests: add unit test for new-session + See https://bugzilla.gnome.org/show_bug.cgi?id=701587 + +2013-06-20 12:16:07 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: emit new-session when new session is created + Only emit new-session when we created a new session for a client, not when a + client picked up a previous session. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=701587 + +2013-06-20 11:17:29 +0200 Alexander Schrab + + * gst/rtsp-server/rtsp-client.c: + client: handle asterisk as path in requests + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=701266 + +2013-06-20 11:14:31 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: handle segment query format mismatch + It's possible that the segment query returns with a different format than what + we asked for, handle this case also. + +2013-06-11 15:28:32 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-media.c: + media: use segment stop in collect_media_stats + Use segment stop instead of duration as range end point. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=701185 + +2013-06-17 16:47:56 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + * tests/check/gst/media.c: + rtsp-media: Do not leak the element in take_pipeline + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=702470 + +2013-06-17 16:18:37 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + rtsp-client: Make configure_client_transport virtual + This patch makes configure_client_transport virtual. The functionality is + needed to handle some weird clients sending multicast transport settings as url + options. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=702173 + +2013-06-12 12:23:56 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + rtsp-client: Make param_set and param_get virtual + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=702072 + +2013-06-05 15:49:45 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: convert_range replaces get_range_times + get_range_times worked for handling UTC ranges for seeks, but we also + need to convert back from NPT to the requested unit in + get_range_string. convert_range is now used for both. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=702084 + +2013-06-14 16:05:59 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-sdp.h: + sdp: cleanup sdp info + We don't need to pass the proto, we can more easily check a boolean. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=702063 + +2013-06-12 15:22:57 +0200 Alexander Schrab + + * gst/rtsp-server/rtsp-sdp.c: + use 0.0.0.0 or :: for c= line instead of server address + +2013-06-12 10:56:16 +0200 Alexander Schrab + + * gst/rtsp-server/rtsp-client.c: + use local address, not remote, in SDP + See https://bugzilla.gnome.org/show_bug.cgi?id=702063 + +2013-06-05 15:18:26 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 098c0d7 to 01a7a46 + +2013-05-29 13:45:00 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: possibility to override range time conversion + Make it possible to override the conversion from GstRTSPTimeRange to + GstClockTimes, that is done before seeking on the media + pipeline. Overriding can be useful for UTC ranges, where the default + conversion gives nanoseconds since 1900. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=701191 + +2013-06-03 12:04:44 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + rtsp-server: Expose the use_client_settings API + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=699935 + +2013-05-30 08:07:48 +0200 Alexander Schrab + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + rtspstream: handle both ipv4 and ipv6 clients + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=701129 + +2013-05-31 15:28:58 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-sdp.c: + Revert "rtsp-sdp: Parse width/height from caps and set SDP attribute" + This reverts commit 5fd034ff1a517db7f629ffcc3ed16839c61f5c97. + We already have a way to place extra attributes in the SDP by using a string + property with prefix x- or a- in the caps. + +2013-05-31 15:27:48 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-sdp.c: + Revert "rtsp-sdp: Parse framerate caps field and set SDP attribute" + This reverts commit d6a4dee03642a2d2c05fec4752dc3ccb60b19494. + We already have a way to place extra attributes in the SDP, just make a string + property in the payloader with a- or x- prefix. + +2013-05-31 15:41:55 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-sdp.c: + rtsp: place a- and x- properties as attributes + application/x-rtp has properties with a- and x- prefixes that should be + placed as attributes in the SDP for the media instead of being added to the + fmtp. + +2013-05-31 12:10:28 +0200 Wim Taymans + + * examples/Makefile.am: + * examples/test-video.c: + example: add TLS example + +2013-05-31 11:42:36 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + server: add support for TLS + Add methods to set and get a TLS certificate. + Add vmethod to configure a new connection. By default, configure the TLS + certificate in a new connection if needed. + +2013-05-31 11:14:17 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + server: remove accept_client vmethod + This vmethod is not very useful so remove it. + +2013-05-30 17:23:51 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: don't crash on NULL GError + +2013-05-30 10:46:33 +0200 Patricia Muscalu + + * gst/rtsp-server/rtsp-session-pool.c: + rtsp-session-pool: corrected session timeout detection + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=701253 + +2013-05-30 10:52:46 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: improve debug + +2013-05-30 07:18:22 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-server.c: + server: refactor connection setup + Let the server accept the socket connection and construct a GstRTSPConnection + from it. Remove the code from the client and let the client only deal with + a fully configure GstRTSPConnection object. + We will need this later when the server will configure the connection for + TLS. + +2013-05-30 06:49:20 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: keep the transport object alive + Keep the transport object alive while we have it as qdata on the + source. + +2013-05-27 12:58:07 +0200 Alexander Schrab + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-server.c: + rtsp-server: Do not crash on nmapping of server + * generate error when gst_rtsp_connection_accept fails + * do not stop accepting incoming connections because + accepting a client fails + https://bugzilla.gnome.org/show_bug.cgi?id=701072 + +2013-05-24 13:39:50 +0200 Alexander Schrab + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: ipv4 adress should not be marked ipv6 even if socket is ipv6 + https://bugzilla.gnome.org/show_bug.cgi?id=700953 + +2013-05-22 03:29:38 +0200 Sebastian Rasmussen + + * gst/rtsp-server/rtsp-sdp.c: + rtsp-sdp: Parse framerate caps field and set SDP attribute + The SDP attribute and its format is described in RFC4566. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=700747 + +2013-05-22 03:29:30 +0200 Sebastian Rasmussen + + * gst/rtsp-server/rtsp-sdp.c: + rtsp-sdp: Parse width/height from caps and set SDP attribute + The SDP attribute and its format is described in RFC6064. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=700747 + +2013-04-29 14:46:30 +0200 Patricia Muscalu + + * gst/rtsp-server/rtsp-sdp.c: + * tests/check/gst/client.c: + rtsp-sdp: add bandwidth line + https://bugzilla.gnome.org/show_bug.cgi?id=699220 + +2013-05-15 10:55:09 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 5edcd85 to 098c0d7 + +2013-04-23 11:28:39 +0200 Ognyan Tonchev + + * tests/check/gst/media.c: + tests: add dynamic payloader prepare/unprepare check + +2013-04-23 10:27:35 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: release lock when removing fakesink + +2013-04-23 10:16:17 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: set elements to NULL before removing + When removing a stream, set the elements to NULL first. This avoids + element-is-not-in-NULL-state errors when we dispose the elements. + +2013-04-22 23:55:48 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 3cb3d3c to 5edcd85 + +2013-04-22 17:34:37 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: listen to pad-removed signals + Listen to the pad-removed signal and remove the stream associated with the + removed pad. + Add signal to be notified of the removed pad. + Remove the fakesink in unprepare() + Fix signatures of the signal methods + +2013-04-22 17:33:30 +0200 Wim Taymans + + * examples/test-sdp.c: + tests: add example of reusable pipelines + +2013-04-22 17:32:31 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add method to get the srcpad + +2013-04-22 16:49:39 +0200 Ognyan Tonchev + + * tests/check/gst/media.c: + check: add media prepare/unprepare test + See https://bugzilla.gnome.org/show_bug.cgi?id=698376 + +2013-04-22 16:40:48 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + media: disconnect from signal handlers in unprepare() + We connected to the pad-added and no-more-pads signals in prepare() so + we need to disconnect from them in unprepare(). + See https://bugzilla.gnome.org/show_bug.cgi?id=698376 + +2013-04-22 16:25:17 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + media: don't free streams array + Don't free the streams array in the unprepare() method, they were not + added in prepare(). + See https://bugzilla.gnome.org/show_bug.cgi?id=698376 + +2013-04-22 16:19:35 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + media: don't unref the pipeline in unprepare + Unprepare() should undo what prepare() does. Because the pipeline is + not created in prepare(), we should not unref it in unprepare() + +2013-04-22 16:09:22 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-stream.c: + stream: clear session and caps for reuse + Set the session and caps to NULL after unref otherwise we might unref + them again later. + See https://bugzilla.gnome.org/show_bug.cgi?id=698376 + +2013-04-15 12:21:54 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-client.c: + client: send out teardown signal before tearing down + The advantage is that in the signal handler you get direct access to + information about what streams are about to get torn down (in the + GstRTSPClientState). + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=697686 + +2013-04-15 12:17:34 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: expose connection + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=697546 + +2013-04-14 17:58:22 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From aed87ae to 3cb3d3c + +2013-04-12 11:34:38 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-media.h: + media: add method to get the base_time of the pipeline + Together with a shared clock, this base-time could eventually be sent to + the client so that it can reconstruct the exact running-time of the clock + on the server. + +2013-04-09 22:35:28 +0200 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-sdp.c: + media: add GstNetTimeProvider support + Add a property to let the media provide a GstNetTimeProvider for its clock. + Make methods to get the clock and nettimeprovider + Add a x-gst-clock property to the SDP with the IP and port number of the nettime + provider and also the current time of the clock. This should make it possible + for (GStreamer) clients to slave their clock to the server clock. + +2013-04-09 21:02:47 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From 04c7a1e to aed87ae + +2013-04-09 20:39:58 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: wait for buffering to complete + Wait for buffering to complete before changing the state to the target state. + +2013-04-09 20:11:35 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: small cleanup + +2013-03-20 12:33:54 +0100 David Svensson Fors + + * tests/check/gst/rtspserver.c: + tests: remove extra unref in test_setup_non_existing_stream + The unref is not needed anymore, teardown runs without it. + https://bugzilla.gnome.org/show_bug.cgi?id=696542 + +2013-03-20 11:28:11 +0100 David Svensson Fors + + * tests/check/gst/rtspserver.c: + tests: GSocketService cleanup in test_bind_already_in_use + Use g_socket_service_stop so the rtspserver test stops listening for + incoming connections in test_bind_already_in_use. + https://bugzilla.gnome.org/show_bug.cgi?id=696541 + +2013-03-22 18:25:07 -0400 Olivier Crête + + * gst/rtsp-server/rtsp-media-factory.c: + rtsp-media-factory: g_signal_connect_object is not thread safe, can't use it here + Instead use a GWeakRef which is safe to use + This is a known GLib bug, see: + https://bugzilla.gnome.org/show_bug.cgi?id=667145 + +2013-02-22 14:17:29 -0500 Olivier Crête + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-sdp.c: + * tests/check/gst/media.c: + * tests/check/gst/rtspserver.c: + rtsp-media/client: Reply to PLAY request with same type of Range + Remember the type of Range from the PLAY request and use the same type for + the reply. + +2013-03-18 09:25:54 +0100 Patricia Muscalu + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * tests/check/gst/client.c: + rtsp-client: expose uri + +2013-03-13 17:46:58 -0400 Olivier Crête + + * tests/check/gst/mediafactory.c: + tests: Hold ref while creating second media + To test if the media aren't shared, make sure we keep the first one while creating a second + otherwise the same memory address may be reused. + +2013-03-12 00:10:18 +0000 Tim-Philipp Müller + + * configure.ac: + configure: remove out-of-date comment + +2013-03-12 00:05:49 +0000 Tim-Philipp Müller + + * .gitignore: + .gitignore: ignore more build files + +2013-03-12 00:03:36 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: use right _LIBS variable for gst-plugins-base libs + +2013-03-11 11:35:14 +0100 Wim Taymans + + * tests/check/Makefile.am: + check: add librtp to libs + +2013-02-20 19:37:51 -0500 Olivier Crête + + * tests/check/gst/rtspserver.c: + tests: Add test to check selecting a port the server will send from + +2013-02-20 18:30:01 -0500 Olivier Crête + + * tests/check/gst/rtspserver.c: + tests: Make sure packets are actually received + +2013-02-19 18:27:20 -0500 Olivier Crête + + * gst/rtsp-server/rtsp-stream.c: + stream: Select unicast address from pool if appropriate + +2013-02-19 16:43:08 -0500 Olivier Crête + + * gst/rtsp-server/rtsp-stream.c: + stream: Properties are always there in Gst 1.0 + +2013-02-19 16:36:20 -0500 Olivier Crête + + * tests/check/gst/addresspool.c: + tests: Add tests for unicast addresses in pool + +2013-02-20 14:26:03 -0500 Olivier Crête + + * gst/rtsp-server/rtsp-address-pool.c: + * tests/check/gst/addresspool.c: + address-pool: Verify that multicast addresses are used for multicast and vice-versa + +2013-02-19 16:34:16 -0500 Olivier Crête + + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-address-pool.h: + * gst/rtsp-server/rtsp-stream.c: + * tests/check/gst/addresspool.c: + address-pool: Add unicast addresses + +2013-02-19 13:19:41 -0500 Olivier Crête + + * configure.ac: + * gst/rtsp-server/rtsp-server.c: + * tests/check/gst/rtspserver.c: + rtsp-server: Limit the number of threads per server instance + If we exceed the maximum, just round robin the clients over the existing + threads. + +2013-02-19 12:31:23 -0500 Olivier Crête + + * gst/rtsp-server/rtsp-server.c: + rtsp-server: No need to store the GMainContext in the client context + +2013-02-18 20:22:18 -0500 Olivier Crête + + * tests/check/gst/rtspserver.c: + tests: Add test for client disconnection + +2013-02-18 20:15:41 -0500 Olivier Crête + + * tests/check/gst/rtspserver.c: + tests: Test client and session timeouts with multiple threads + +2013-02-18 14:59:58 -0500 Olivier Crête + + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-mount-points.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session.c: + Document locking and its order + +2013-02-15 20:02:31 -0500 Olivier Crête + + * tests/check/gst/rtspserver.c: + tests: Test that slow DESCRIBE don't block other clients + +2013-02-14 19:52:09 -0500 Olivier Crête + + * tests/check/gst/client.c: + tests: Add tests for client-requested multicast address + +2013-02-14 13:44:54 -0500 Olivier Crête + + * docs/libs/gst-rtsp-server-sections.txt: + docs: Put the various functions in the right sections + +2013-02-14 13:38:07 -0500 Olivier Crête + + * docs/libs/gst-rtsp-server-docs.sgml: + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-address-pool.h: + docs: Generate docs for GstRTSPAddressPool + +2013-02-13 18:32:20 -0500 Olivier Crête + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + client: Check client provided addresses against the address pool + +2013-02-13 18:01:43 -0500 Olivier Crête + + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-address-pool.h: + * tests/check/gst/addresspool.c: + address-pool: Add API to request a specific address from the pool + Also add relevant unit tests. + +2013-02-12 19:34:24 -0500 Olivier Crête + + * tests/check/gst/mediafactory.c: + tests: Check the passing around of a RTSPAddressPool + Make sure the RTSPAddressPool is propagated from the MediaFactory all the + way down to the stream. + +2013-02-12 16:34:37 -0500 Olivier Crête + + * tests/check/gst/addresspool.c: + tests: Add more tests for the address pool + +2013-02-12 16:29:25 -0500 Olivier Crête + + * gst/rtsp-server/rtsp-address-pool.c: + address-pool: Fix off by one error + When splitting a port range, the port after a skip is not part of range. + +2013-03-07 00:04:19 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 2de221c to 04c7a1e + +2013-02-07 16:18:08 -0600 George McCollister + + * configure.ac: + configure: replace deprecated AM_CONFIG_HEADER with AC_CONFIG_HEADERS + AM_CONFIG_HEADER was removed in automake 1.13 + https://bugzilla.gnome.org/show_bug.cgi?id=693368 + +2013-01-28 20:45:44 +0100 Stefan Sauer + + * common: + Automatic update of common submodule + From a942293 to 2de221c + +2013-01-28 10:31:50 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: make sure the watch exists while sending data + Protect the send_func with a lock. This allows us to wait for sending + to complete before changing the send_func and user_data. We add an + extra ref to the watch to make sure that it remains valid during + sending. + When closing the connection, set the send_func to NULL + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=692433 + +2013-01-16 12:16:32 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: use GST_*_1_0 environment variables everywhere + The _1_0 suffixed environment variables override the + non-suffixed ones, so if we're in an environment that + sets the _1_0 suffixed ones, such as jhbuild, we need + to set those to make sure ours actually always get + used. + +2013-01-15 15:09:24 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From acb04d9 to a942293 + +2012-12-14 11:58:29 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: set the client backlog + Set the client backlog to a reasonable default + +2012-12-04 09:47:35 +0100 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + rtsp-media: Make the element a constructor parameter + https://bugzilla.gnome.org/show_bug.cgi?id=689594 + +2012-12-04 01:05:31 +0100 Sebastian Rasmussen + + * docs/libs/Makefile.am: + docs: Link with gcov library when gcov is enabled + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=689583 + +2012-11-30 15:03:15 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: match prepare with unprepare + Really unprepare when there were an equal amount of prepare calls. + +2012-11-30 14:58:46 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: media has to be unprepared in finalize + Because unprepare takes away the last ref on the media. + +2012-11-30 14:36:30 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + Revert "client: never call gst_rtsp_media_unprepare, let gst_rtsp_media_finalize do it" + This reverts commit ba5b78ff2ff223049188eb456e228c709ccd3e05. + We can't use the refcount to trigger unprepare because it is the unprepare call + that removes the last refcount after all messages are consumed. What we should + probably do is make a prepared refcount and only unprepare when the refcount + reaches 0. + +2012-11-30 13:35:05 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: let the source unref the last media ref + the last ref to the media is held by the source so we don't need to add more ref + and unrefs, we simply destroy the media when the source is gone. + +2012-11-30 12:54:10 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: improve debug + +2012-11-30 12:53:02 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: check state + Make sure we are in the right state when collecting the position and duration. + Only make ourselves PREPARED when we were previously PREPARING. + +2012-11-30 10:05:48 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: use g_object_ref/unref for GObjects + +2012-11-30 07:05:25 +0100 Alessandro Decina + + * gst/rtsp-server/rtsp-client.c: + client: never call gst_rtsp_media_unprepare, let gst_rtsp_media_finalize do it + Calling gst_rtsp_media_unprepare breaks shared medias. Just unref + GstRTSPMedia instances and let gst_rtsp_media_finalize unprepare when a media + isn't being used anymore. + +2012-11-30 06:17:46 +0100 Alessandro Decina + + * gst/rtsp-server/rtsp-media.c: + Fix compiler warning + +2012-11-30 06:14:49 +0100 Alessandro Decina + + * gst/rtsp-server/rtsp-media-factory-uri.c: + Add missing g_type_class_add_private in GstRTSPMediaFactoryURI + +2012-11-29 17:21:12 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session-media.h: + small cleanup + +2012-11-29 17:20:56 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * tests/check/gst/media.c: + media: avoid element leak + +2012-11-29 17:20:26 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: require an element in media constructor + +2012-11-29 17:07:30 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + Revert "client: TEARDOWN brings that state to Init again" + This reverts commit 4b61fdad85a3ca84752bf074fdb2fa203954b32e. + The object is already disposed, there is no point in setting the state. + +2012-11-29 12:30:20 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: TEARDOWN brings that state to Init again + +2012-11-29 11:11:05 +0100 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + * examples/test-auth.c: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media-factory-uri.h: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-mount-points.c: + * gst/rtsp-server/rtsp-mount-points.h: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-media.h: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + * tests/check/gst/media.c: + rtsp: make object details private + Make all object details private + Add methods to access private bits + +2012-11-28 14:50:47 +0100 Wim Taymans + + * tests/check/Makefile.am: + * tests/check/gst/media.c: + tests: add media tests + +2012-11-28 14:45:30 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: check if prepared for some methods + Check that the media object is prepared before doing seek and getting the + current position etc. + Add some g_return checks. + +2012-11-28 12:40:46 +0100 Wim Taymans + + * tests/check/Makefile.am: + * tests/check/gst/mediafactory.c: + tests: add mediafactory test + +2012-11-28 12:40:18 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: improve debug + +2012-11-28 12:39:37 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: unref pipeline in finalize to avoid leaking it + +2012-11-28 12:10:47 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media.c: + rtsp: use gst_object_unref on GstObjects + +2012-11-28 12:10:14 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + media-factory: require an url + +2012-11-28 11:40:33 +0100 Wim Taymans + + * examples/test-uri.c: + examples: fix include + +2012-11-28 11:17:27 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.h: + server: remove unused include + +2012-11-28 11:07:57 +0100 Wim Taymans + + * tests/check/Makefile.am: + * tests/check/gst/mountpoints.c: + tests: add test for mountpoints + +2012-11-28 11:05:08 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: fix factory leak + Keep the factory in the state object only for authorization checks and make + sure we unref it on failure. Also don't keep invalid objects in the state + object. + +2012-11-28 10:40:14 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-mount-points.c: + mounts: add g_return_if guards + +2012-11-27 12:51:55 +0100 Wim Taymans + + * tests/check/gst/client.c: + tests: add more tests + +2012-11-27 12:33:02 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: improve debug + +2012-11-27 12:24:21 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: improve debug and fix leaks + Cleanup the uri and session when there is a bad request. + +2012-11-27 12:17:05 +0100 Wim Taymans + + * common: + update common + +2012-11-27 12:13:59 +0100 Wim Taymans + + * tests/check/gst/client.c: + test: add test for session in options request + +2012-11-27 12:11:41 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: use 454 when session can't be found + We should use 454 when a session can't be found because there was no session + pool configured in the server. This is not a server configuration problem + because the server on which the request is done might not be the same one that + will keep the sessions for us and so it does not need to support sessions. + +2012-11-27 11:17:45 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: only free connection when there is one + It's possible that the client doesn't have a connection when we try to free it. + +2012-11-27 11:17:31 +0100 Wim Taymans + + * tests/check/Makefile.am: + * tests/check/gst/client.c: + tests: add unit test for the client object + +2012-11-26 17:35:51 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: small cleanup + +2012-11-26 17:34:35 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.h: + client: remove unused include + +2012-11-26 17:34:24 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: fix compilation + +2012-11-26 17:28:29 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: call destroy without the lock + +2012-11-26 17:20:39 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: make the client usable without a socket + Make a method to let the client handle a message and a callback when the client + wants us to send a response message back. This makes it possible to also use the + client object without the sockets, which should make it easier to test. + +2012-11-26 16:45:04 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: small cleanup + +2012-11-26 16:39:26 +0100 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-server.c: + client: remove reference to server + We don't need to keep a ref to the server + +2012-11-26 16:30:16 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: add locking + Also add some g_return_if() + +2012-11-26 13:37:20 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: log more errors + +2012-11-26 13:35:48 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: fix compilation + +2012-11-26 13:16:59 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: add generic close-after-send support + Add a property to send_response() to close the connection after the response has + been sent to the client. + +2012-11-26 12:34:05 +0100 Wim Taymans + + * docs/README: + * docs/libs/gst-rtsp-server-docs.sgml: + * docs/libs/gst-rtsp-server-sections.txt: + * docs/libs/gst-rtsp-server.types: + * examples/test-auth.c: + * examples/test-launch.c: + * examples/test-mp4.c: + * examples/test-multicast.c: + * examples/test-multicast2.c: + * examples/test-ogg.c: + * examples/test-readme.c: + * examples/test-sdp.c: + * examples/test-uri.c: + * examples/test-video.c: + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media-mapping.c: + * gst/rtsp-server/rtsp-media-mapping.h: + * gst/rtsp-server/rtsp-mount-points.c: + * gst/rtsp-server/rtsp-mount-points.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + * tests/check/gst/rtspserver.c: + MediaMapping -> MountPoints + Describes better what the object manages. + +2012-11-26 09:36:09 +0100 Wim Taymans + + * configure.ac: + configure: bump required version of -base + +2012-11-21 17:21:28 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: fix seeking + +2012-11-21 16:41:56 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: support more Range formats + Use the new -base methods to convert the Range string into a seek start and stop + value. + +2012-11-21 16:41:37 +0100 Wim Taymans + + * examples/test-launch.c: + examples: fix whitespace + +2012-11-20 13:34:46 +0100 Wim Taymans + + * examples/test-auth.c: + test-auth: add example of how to remove sessions + Add an example of the session filter api. + +2012-11-20 12:47:49 +0100 Wim Taymans + + * examples/test-uri.c: + test-uri: remove mapping example + +2012-11-20 12:47:20 +0100 Wim Taymans + + * examples/test-uri.c: + test-uri: fix callback signature + +2012-11-20 12:29:55 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + factory: keep ref to factory while media active + While the media from a factory is alive, keep a ref to the factory. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=663555 + +2012-11-20 12:29:26 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + factory-uri: add some debug + +2012-11-20 12:24:13 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: set udp sources to PLAYING + Set the UDP sources to PLAYING and locked state before we add it to the pipeline + so that it doesn't cause our pipeline to produce ASYNC-DONE. + +2012-11-20 12:10:16 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + factory-uri: take ref to factory + Take a ref to the factory that we place in our list. + +2012-11-20 11:30:09 +0100 Wim Taymans + + * tests/Makefile.am: + * tests/test-reuse.c: + test: add test for server reuse + See https://bugzilla.gnome.org/show_bug.cgi?id=688395 + +2012-11-15 14:02:37 +0100 David Svensson Fors + + * gst/rtsp-server/rtsp-server.c: + server: start and stop multiple times + Stop listening on the RTSP port when the GSource is removed, so clients + can't connect and the server can be started again. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=688395 + +2012-11-20 11:24:35 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: fix small leak + +2012-11-20 09:42:51 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: unref source in finish_unprepare + The source is created in prepare, unref it in finish_unprepare. + See https://bugzilla.gnome.org/show_bug.cgi?id=688707 + +2012-11-19 15:47:08 +0100 David Svensson Fors + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + rtsp-media: remove bus watch before finalizing + * A GDestroyNotify function is set for the bus watch in gst_rtsp_media_prepare. + * An extra media ref is added for the bus watch. This extra ref is unreffed by + the GDestroyNotify function. + * gst_rtsp_media_unprepare destroys the source so the bus watch is removed. + * GstRTSPClient, which calls gst_rtsp_media_prepare, also calls + gst_rtsp_media_unprepare before unreffing the media. + This way, the bus watch will be removed before the media is finalized. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=688707 + +2012-11-17 14:51:52 +0100 Alessandro Decina + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: wait until the TEARDOWN response is sent to close the connection + Responses can be sent async so we need to wait until the TEARDOWN response has + been written before we close the connection to the client. This avoids the risk + of writing/polling closed sockets. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=688535 + +2012-11-19 15:44:27 +0100 David Svensson Fors + + * gst/rtsp-server/rtsp-stream.c: + rtsp-stream: plug socket leak + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=688703 + +2012-11-19 11:31:12 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 6bb6951 to a72faea + +2012-11-17 00:11:27 +0000 Tim-Philipp Müller + + * gst/rtsp-server/rtsp-media-factory-uri.c: + rtsp-server: don't use deprecated API + +2012-11-17 00:03:42 +0000 Tim-Philipp Müller + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: fix unused-but-set-variable compiler warning + rtsp-client.c:1260:21: error: variable 'protocols' set but not used + +2012-11-15 17:11:16 +0100 Wim Taymans + + * TODO: + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-client.c: + rtsp: cleanups + +2012-11-15 16:52:42 +0100 Wim Taymans + + * examples/Makefile.am: + * examples/test-multicast2.c: + examples: add another multicast example + Add an example for how to configure separate multicast ranges for each media + stream. + +2012-11-15 16:21:51 +0100 Wim Taymans + + * examples/test-multicast.c: + test: set shared + +2012-11-15 16:18:29 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-media.h: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + stream: use the address managed by the stream + Use the address managed by the stream for multicast. This allows us to have 1 + multicast address for each stream. + Because the address is now managed by the stream we don't have to pass it around + anymore. + Set the address pool on the streams. + +2012-11-15 16:15:20 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-stream.c: + rtsp: improve debug + +2012-11-15 15:41:42 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add signal for new streams + This allows applications to listen for new streams and configure properties on + them, like the address pool. + +2012-11-15 15:41:19 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: configure address pool in new streams + +2012-11-15 15:36:21 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add methods to deal with address pool + Add methods to get and set the address pool for the stream + Add method to allocate and get the multicast addresses for this stream. + +2012-11-15 15:32:43 +0100 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: remove MTU property + It is a stream property + +2012-11-15 15:29:35 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: set blocksize only on stream + Set the blocksize only on the current stream. + +2012-11-15 13:52:07 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: share src and sink sockets + the allocated socket is in the used-socket property, not socket. + +2012-11-15 13:25:14 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-address-pool.h: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-media.h: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + * tests/check/gst/addresspool.c: + rtsp: make address-pool return an address object + Return a boxed GstRTSPAddress from the GstRTSPAddressPool. This allows us to + store more info in the structure and allows us to more easily return the address + to the right pool when no longer needed. + Pass the address to the StreamTransport so that we can return it to the pool + when the stream transport is freed or changed. + +2012-11-15 13:22:54 +0100 Wim Taymans + + * examples/Makefile.am: + * examples/test-multicast.c: + examples: add multicast example + Show how to set up the multicast address pool so that media can be + server with multicast. + +2012-11-14 17:23:59 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + rtsp: use AddressPool + Remove the multicast_group property. + Use the configured addresspool to allocate multicast addresses. + +2012-11-14 16:17:33 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-address-pool.h: + address-pool: add clear method + +2012-11-14 16:10:45 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-address-pool.c: + address-pool: small cleanups + +2012-11-14 15:50:42 +0100 Wim Taymans + + * tests/check/Makefile.am: + * tests/check/gst/addresspool.c: + tests: add addresspool unit test + +2012-11-14 15:49:06 +0100 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-address-pool.c: + * gst/rtsp-server/rtsp-address-pool.h: + address-pool: add object to manage multicast addresses + Make an object that can manage a rage of multicast addresses and ports. + +2012-11-13 12:05:42 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: set default max-threads property + +2012-11-13 11:54:17 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: wait for concurrent _prepare + If a prepare is busy, wait for the result. + +2012-11-13 11:49:08 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: add lock around message handler + We don't want to dispatch messages while we are still processing the result of + the state change. + +2012-11-13 11:15:35 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add lock to protect state changes + +2012-11-13 11:14:49 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: add locking + +2012-11-12 17:11:18 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + * gst/rtsp-server/rtsp-stream.c: + stream-transport: add keep-alive method + +2012-11-12 17:06:42 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + * gst/rtsp-server/rtsp-stream.c: + stream-transport: add method to handle RTP/RTCP + Call new methods instead of poking into the structures directly. + +2012-11-12 16:51:03 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-media.h: + session-media: add locking + +2012-11-12 16:42:37 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + session: add locking + +2012-11-12 16:30:16 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: free old socket + +2012-11-12 16:18:57 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-mapping.c: + * gst/rtsp-server/rtsp-media-mapping.h: + mapping: add locking + +2012-11-12 16:14:19 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + media-factory: add locking + +2012-11-12 16:03:21 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + auth: add locking + +2012-11-12 15:53:28 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + server: add max-thread property + +2012-11-12 15:29:39 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + server: use a threadpool for the mainloops + +2012-11-12 14:30:43 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: rename method + gst_rtsp_client_create_from_socket -> gst_rtsp_client_use_socket: we + don't really create the client from the socket, we use the socket for the + client. + +2012-11-12 14:09:09 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-server.c: + server: rework maincontext handling in clients + Make a separate method to attach a client to a MainContext. + Let the server decide in what GMainContext the client will operate and give this + context to the client in attach. Then the server can later decide to use a + separate thread for each client or just use the mainthread. + +2012-11-12 12:40:34 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + session: move session header code in session object + +2012-11-04 00:14:25 +0000 Tim-Philipp Müller + + * COPYING: + * COPYING.LIB: + * examples/test-auth.c: + * examples/test-launch.c: + * examples/test-mp4.c: + * examples/test-ogg.c: + * examples/test-readme.c: + * examples/test-sdp.c: + * examples/test-uri.c: + * examples/test-video.c: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media-factory-uri.h: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media-mapping.c: + * gst/rtsp-server/rtsp-media-mapping.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-params.c: + * gst/rtsp-server/rtsp-params.h: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-sdp.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-media.h: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + * tests/check/gst/rtspserver.c: + * tests/test-cleanup.c: + Fix FSF address + +2012-10-28 13:48:44 +0100 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session.c: + rtsp-server: added annotations to indicate type of ownership transfer of return values + https://bugzilla.gnome.org/show_bug.cgi?id=680777 + +2012-10-28 15:37:51 +0000 Tim-Philipp Müller + + * configure.ac: + No need to define GST_USE_UNSTABLE_API any more, 1.0 is stable now + +2012-10-28 15:09:04 +0000 Tim-Philipp Müller + + * Makefile.am: + * bindings/Makefile.am: + * bindings/vala/Makefile.am: + * bindings/vala/gst-rtsp-server-0.10.deps: + * bindings/vala/gst-rtsp-server-0.10.vapi: + * bindings/vala/packages/gst-rtsp-server-0.10.deps: + * bindings/vala/packages/gst-rtsp-server-0.10.files: + * bindings/vala/packages/gst-rtsp-server-0.10.gi: + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + * bindings/vala/packages/gst-rtsp-server-0.10.namespace: + * configure.ac: + bindings: remove vala bindings + They'll be reunited with the other GStreamer bindings + https://bugzilla.gnome.org/show_bug.cgi?id=680777 + +2012-10-28 00:23:57 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-media.h: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + rtsp: only create transport when needed + Only create the StreamTransport when configured. + +2012-10-27 23:53:35 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: small cleanup + +2012-10-27 23:49:24 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + rtsp: refactor configuration of transport + Move the configuration of the transport to a place where it makes + more sense. + +2012-10-27 21:26:55 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: refactor transport parsing + +2012-10-27 21:05:03 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: refuse to change the MTU on shared media + If we change the MTU of chared media, it changes for all clients. + We don't want to set the MTU to something large for clients that + stream over UDP. + +2012-10-27 11:53:51 +0200 Wim Taymans + + * examples/test-mp4.c: + * gst/rtsp-server/rtsp-media.c: + small fixes to docs and debug + +2012-10-26 17:29:30 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-stream.c: + stream: transports must already have been removed + +2012-10-26 17:28:10 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + stream: improve join and leave of the pipeline + simplify code + Do the cleanup properly + Add some docs + +2012-10-26 15:23:16 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: move unprepare below default implementation + Makes it easier to find the default implementation + +2012-10-26 15:21:50 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: signal unprepared when we actually finish + +2012-10-26 15:19:23 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: no need to unlock, unprepare does that when needed + +2012-10-26 12:33:21 +0200 Wim Taymans + + * docs/libs/gst-rtsp-server-sections.txt: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media-mapping.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-params.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + * gst/rtsp-server/rtsp-stream-transport.h: + * gst/rtsp-server/rtsp-stream.h: + docs: update docs + +2012-10-26 12:04:02 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-mapping.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + rtsp: fix MTU setting + Fix setting of the MTU. There is no need for a vmethod. + +2012-10-26 11:02:43 +0200 Wim Taymans + + * docs/README: + docs: update docs + +2012-10-26 11:24:55 +0100 Tim-Philipp Müller + + * configure.ac: + configure: bump version number after refactoring + +2012-10-25 21:29:58 +0200 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-session-media.c: + * gst/rtsp-server/rtsp-session-media.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + * gst/rtsp-server/rtsp-stream-transport.c: + * gst/rtsp-server/rtsp-stream-transport.h: + * gst/rtsp-server/rtsp-stream.c: + * gst/rtsp-server/rtsp-stream.h: + rtsp: massive refactoring + Make GObjects from the remaining simple structures. + Remove GstRTSPSessionStream, it's not needed. + Rename GstRTSPMediaStream -> GstRTSPStream: It is shorter + Rename GstRTSPMediaTrans -> GstRTSPStreamTransport: It describes how + a GstRTSPStream should be transported to a client. + Rename GstRTSPMediaFactory::get_element -> create_element because that + more accurately describes what it does. + Make nice methods instead of poking in the structures. + Move some methods inside the relevant object source code. + Use GPtrArray to store objects instead of plain arrays, it is more + natural and allows us to more easily clean up. + Move the allocation of udp ports to the Stream object. The Stream object + contains the elements needed to stream the media to a client. + Improve the prepare and unprepare methods. Unprepare should now undo + everything prepare did. Improve also async unprepare when doing EOS on + shutdown. Make sure we always unprepare correctly. + +2012-10-23 22:11:17 +0200 Sebastian Rasmussen + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: Unref server address clients connected to + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=686725 + +2012-10-22 16:09:24 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-server.c: + rtsp-server: don't ref server socket if it is NULL + Fixes test_bind_already_in_use unit test again after commit 6a497440. + https://bugzilla.gnome.org/show_bug.cgi?id=686644 + +2012-10-22 16:29:09 +0200 Sebastian Rasmussen + + * tests/check/Makefile.am: + tests: Add libgio link dependency + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=686647 + +2012-10-01 20:03:43 +0200 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-media-mapping.c: + * gst/rtsp-server/rtsp-media-mapping.h: + rtsp-media-mapping: rename find_media vfunc to find_factory + The virtual method and class method should have the same name + so it is correctly represented in GIR file + https://bugzilla.gnome.org/show_bug.cgi?id=680777 + +2012-10-01 19:46:15 +0200 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-mapping.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session.c: + rtsp-server: fixed comments and GIR annotations + https://bugzilla.gnome.org/show_bug.cgi?id=680777 + +2012-10-12 07:18:19 +0200 Alessandro Decina + + * gst/rtsp-server/rtsp-media-mapping.c: + media-mapping: fix transfer mode for gst_rtsp_media_mapping_add_factory + +2012-10-12 07:08:57 +0200 Alessandro Decina + + * gst/rtsp-server/rtsp-server.c: + rtsp-server: allow binding on port 0 (binds on a random port) + +2012-10-12 06:21:24 +0200 Alessandro Decina + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + rtsp-server: add bound-port property + bound-port can be used to retrieve the port number when the server is bound on + port 0, which binds on a random port. + +2012-10-12 06:11:36 +0200 Alessandro Decina + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + rtsp-media-factory: make ::get_element overridable by GI bindings + The way to annotate vfuncs with GI seems to be to create an invoker (GI term) + for them and to annotate the invoker. Add gst_rtsp_media_factory_get_element() + as the invoker for ::get_element(), making it overridable by GI generated + bindings. + +2012-10-12 06:07:07 +0200 Alessandro Decina + + * gst/rtsp-server/rtsp-media-factory-uri.c: + rtsp-media-factory-uri: don't autoplug parsers in a loop + Stop autoplugging parsers if caps have parsed=true set. Fixes autoplugging + h264parse forever. + +2012-10-06 15:49:07 +0200 Alessandro Decina + + * gst/rtsp-server/Makefile.am: + Explicitly link against gio. Fix link error on mac. + +2012-10-10 11:13:10 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-session.c: + session: add ttl to the transport header in SETUP + See https://bugzilla.gnome.org/show_bug.cgi?id=685561 + +2012-10-10 11:06:02 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media.c: + client: Use client transport settings for multicast if allowed. + This patch makes it possible for the client to send transport settings for + multicast (destination && ttl). Client settings must be explicitly allowed or + the server will use its own settings. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=685561 + +2012-10-06 15:02:27 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 6c0b52c to 6bb6951 + +2012-10-01 16:13:50 +0200 Patricia Muscalu + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: do not destroy the rtsp watch + Don't destroy the client watch while dispatching. The rtsp watch is + automatically destroyed after the rtsp watch function closed() has + been called. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=685220 + +2012-09-22 16:11:48 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 4f962f7 to 6c0b52c + +2012-09-10 16:25:57 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-media.c: + media: fix check for seekability + +2012-09-07 17:14:30 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: use more GIO + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=681593 + +2012-09-07 17:14:10 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: remove obsolete includes + +2012-09-03 17:33:17 -0700 Aleix Conchillo Flaque + + rtsp-media: also initialize transports in on_ssrc_active (bug #683304) + * gst/rtsp-server/rtsp-media.c: GstRTSPMediaStream transports might not + be available in "on_new_ssrc". The transports are added in + gst_rtsp_media_set_state when going to PLAYING state. However, + "on_new_ssrc" might be called before this happens. + https://bugzilla.gnome.org/show_bug.cgi?id=683304 + +2012-09-03 10:48:14 -0700 Aleix Conchillo Flaque + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + rtsp-client: add signals for rtsp requests (fixes #683287) + +2012-08-30 12:03:27 -0700 Aleix Conchillo Flaque + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + add new-session signal to rtsp-client (fixes #683058) + +2012-08-22 13:34:55 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From 668acee to 4f962f7 + +2012-08-15 15:54:32 +0200 Patricia Muscalu + + * gst/rtsp-server/rtsp-server.c: + * tests/check/gst/rtspserver.c: + rtsp-server: fixed segfault in gst_rtsp_server_create_socket + Do not assume that *error is set in g_socket_address_enumerator_next. + Added test_bind_already_in_use unit-test. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=681914 + +2012-08-05 16:43:53 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 94ccf4c to 668acee + +2012-07-18 15:54:49 +0200 Patricia Muscalu + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + rtsp-client: make create_sdp virtual method + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=680173 + +2012-07-23 08:48:25 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 98e386f to 94ccf4c + +2012-07-10 11:39:58 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: fix docs + +2012-07-03 18:06:00 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + rtsp-server: use an existing socket to establish HTTP tunnel + Make it possible to transfer a socket from an HTTP server to be used as + an RTSP over HTTP tunnel. + +2012-07-03 13:26:30 +0200 Ognyan Tonchev + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + rtsp: Handle the blocksize parameter + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=679325 + +2012-06-25 14:28:10 +0200 Sebastian Rasmussen + + * tests/check/Makefile.am: + * tests/check/gst/rtspserver.c: + Have unit test get header from source dir, not installed dir + This makes compilation of unit tests work in a build directory other + than the source directory. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=678789 + +2012-06-23 15:06:11 +0100 Tim-Philipp Müller + + * gst/rtsp-server/rtsp-media.c: + rtsp-media: update for gst_element_make_from_uri() changes + +2012-06-19 15:25:36 +0200 David Svensson Fors + + * configure.ac: + * tests/Makefile.am: + * tests/check/Makefile.am: + * tests/check/gst/rtspserver.c: + rtsp: add unit test + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=678076 + +2012-06-13 11:43:17 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-media.c: + rtsp-media: don't collect media stats when going to NULL + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=678015 + +2012-06-14 09:59:06 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: don't leak transports + +2012-06-12 14:45:39 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: free transport on no_stream in SETUP handler + +2012-06-12 14:33:35 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: changed session media iteration + In client_unlink_session: now don't iterate in session->medias + list where items are removed by gst_rtsp_session_release_media. + Instead, repeatedly remove the first item. + +2012-06-12 13:39:35 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: don't use g_object_unref on GstRTSPSessionMedia + GstRTSPSessionMedia is not a GObject type. When the + GstRTSPSession is freed, it will free the media. + +2012-06-12 13:36:57 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-media-factory.c: + factory: plug pad leak in collect_streams + In gst_rtsp_media_factory_collect_streams: unref the srcpad that + was retrieved using gst_element_get_static_pad. gst_ghost_pad_new + will take one reference, and the other reference will otherwise + give a memory leak. + +2012-05-25 16:43:38 +0200 Sebastian Rasmussen + + * configure.ac: + configure: suppress some warnings when debug is disabled + Warnings about unused variables should be suppressed if core has the + debug system disabled. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=676824 + +2012-06-09 17:41:05 +0100 Tim-Philipp Müller + + * docs/libs/Makefile.am: + docs: fix build in uninstalled setup + Include gst-plugins-base libs properly. + +2012-05-25 16:38:15 +0200 Sebastian Rasmussen + + * docs/libs/gst-rtsp-server.types: + docs: include headers defining rtsp-server object types + Fixes compiler warnings during docs build. + https://bugzilla.gnome.org/show_bug.cgi?id=676824 + +2012-05-25 17:11:53 +0200 Sebastian Rasmussen + + * configure.ac: + configure: Add warning flags for compiler when configuring + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=676824 + +2012-06-08 15:07:06 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From 03a0e57 to 98e386f + +2012-06-06 18:20:49 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From 1fab359 to 03a0e57 + +2012-06-06 14:49:02 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-client.c: + client: fix GSocketAddress leak in gst_rtsp_client_accept + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=677463 + +2012-06-01 10:30:58 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From f1b5a96 to 1fab359 + +2012-05-31 13:11:43 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 92b7266 to f1b5a96 + +2012-05-30 12:48:51 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From ec1c4a8 to 92b7266 + +2012-05-30 11:27:31 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 3429ba6 to ec1c4a8 + +2012-05-22 15:37:25 +0200 David Svensson Fors + + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-server.c: + rtsp: fix compiler warnings + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=676500 + +2012-05-13 15:59:10 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From dc70203 to 3429ba6 + +2012-05-11 09:42:47 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + rtsp-server: port to new thread API + +2012-04-16 09:11:54 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 6db25be to dc70203 + +2012-04-13 15:27:22 +0200 Sebastian Dröge + + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + rtsp-server: Fix compilation and compiler warnings + +2012-04-13 13:49:08 +0200 Sebastian Dröge + + * autogen.sh: + * configure.ac: + * gst/rtsp-server/Makefile.am: + configure: Modernize autotools setup a bit + Also we now only create tar.bz2 and tar.xz tarballs. + +2012-04-13 13:39:40 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 464fe15 to 6db25be + +2012-04-05 18:45:43 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 7fda524 to 464fe15 + +2012-04-04 14:45:55 +0200 Sebastian Dröge + + * configure.ac: + * docs/libs/Makefile.am: + * docs/version.entities.in: + * gst-rtsp.spec.in: + * gst/rtsp-server/Makefile.am: + * pkgconfig/Makefile.am: + * pkgconfig/gstreamer-rtsp-server-uninstalled.pc.in: + * pkgconfig/gstreamer-rtsp-server.pc.in: + * tests/Makefile.am: + rtsp-server: Update versioning + +2012-03-29 15:12:21 +0200 Sebastian Dröge + + Merge remote-tracking branch 'origin/0.10' + Conflicts: + gst/rtsp-server/rtsp-session-pool.c + +2012-03-27 10:13:20 +0200 Sebastian Dröge + + * gst/rtsp-server/rtsp-session-pool.c: + rtsp-server: Don't use deprecated GLib API + +2012-03-26 12:23:36 +0200 Wim Taymans + + Replace master with 0.11 + +2012-03-26 12:22:05 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2012-03-26 12:20:51 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2012-03-19 10:48:09 +0000 Vincent Penquerc'h + + * docs/README: + A couple minor typo fixes + +2012-03-13 18:10:53 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: fix state of the appqueue + +2012-03-13 16:06:50 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + factory: use videoconvert + +2012-03-13 16:02:47 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + factory: change to new style caps + +2012-03-07 15:03:55 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-pool.c: + rtsp-server: port to GIO + Port to GIO + +2012-03-07 15:03:24 +0100 Wim Taymans + + * configure.ac: + configure: fix build + +2012-02-29 15:56:06 +0000 Tim-Philipp Müller + + * docs/README: + docs: fix for gst_rtsp_server_set_port() -> _set_service() + https://bugzilla.gnome.org/show_bug.cgi?id=666548 + +2012-02-13 11:42:51 +0000 Tim-Philipp Müller + + * configure.ac: + * examples/Makefile.am: + First rule of gst-rtsp-server club: don't talk about gst-phonon + +2012-02-13 11:40:44 +0000 Tim-Philipp Müller + + * configure.ac: + * pkgconfig/Makefile.am: + * pkgconfig/gst-rtsp-server-uninstalled.pc.in: + * pkgconfig/gst-rtsp-server.pc.in: + * pkgconfig/gstreamer-rtsp-server-uninstalled.pc.in: + * pkgconfig/gstreamer-rtsp-server.pc.in: + pkg-config: rename gst-rtsp-server-0.11.pc to gstreamer-rtsp-server-0.11.pc + For consistency with all other modules. + +2012-02-13 11:06:33 +0000 Tim-Philipp Müller + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: update for new map API + +2012-02-13 10:37:37 +0000 Tim-Philipp Müller + + * .gitignore: + * bindings/Makefile.am: + * bindings/python/Makefile.am: + * bindings/python/arg-types.py: + * bindings/python/codegen/Makefile.am: + * bindings/python/codegen/__init__.py: + * bindings/python/codegen/argtypes.py: + * bindings/python/codegen/code-coverage.py: + * bindings/python/codegen/codegen.py: + * bindings/python/codegen/definitions.py: + * bindings/python/codegen/defsparser.py: + * bindings/python/codegen/docextract.py: + * bindings/python/codegen/docgen.py: + * bindings/python/codegen/fileprefix.override: + * bindings/python/codegen/fileprefixmodule.c: + * bindings/python/codegen/h2def.py: + * bindings/python/codegen/mergedefs.py: + * bindings/python/codegen/mkskel.py: + * bindings/python/codegen/override.py: + * bindings/python/codegen/reversewrapper.py: + * bindings/python/codegen/scmexpr.py: + * bindings/python/rtspserver-types.defs: + * bindings/python/rtspserver.defs: + * bindings/python/rtspserver.override: + * bindings/python/rtspservermodule.c: + * bindings/python/test.py: + * configure.ac: + python: remove pygst-based python bindings + pygi is the future, apparently. + +2012-01-25 14:12:41 +0100 Thomas Vander Stichele + + * common: + Automatic update of common submodule + From c463bc0 to 7fda524 + +2012-01-25 11:40:59 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 2a59016 to c463bc0 + +2012-01-18 16:48:41 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 0807187 to 2a59016 + +2012-01-04 19:56:02 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 11f0cd5 to 0807187 + +2011-12-09 11:00:46 +0100 Wim Taymans + + * examples/test-auth.c: + example: update for new caps + +2011-12-09 10:53:30 +0100 Wim Taymans + + * examples/test-video.c: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + rtsp-server: port some more to 0.11 + Fix caps. + Remove bufferlist stuff + Update for new API. + Add queue before appsink now that preroll-queue-len is gone. + Update for request pad changes. + +2011-11-03 16:14:03 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-11-03 16:06:23 +0100 Fabian Deutsch + + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + bindings: Fix vala binding of gst_rtsp_media_mapping_add_factory to transfer ownership. + Signed-off-by: Fabian Deutsch + +2011-11-03 16:06:23 +0100 Fabian Deutsch + + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + bindings: Fix vala binding of gst_rtsp_media_mapping_add_factory to transfer ownership. + Signed-off-by: Fabian Deutsch + +2011-11-03 12:58:42 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-11-03 12:55:24 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add a seekable boolean + Maintain the seekable state with a new variable instead of reusing the + is_live variable. + +2011-09-16 11:31:17 -0400 Victor Gottardi + + * gst/rtsp-server/rtsp-media.c: + Disallow seek in live media + +2011-11-03 11:58:42 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-11-03 10:48:40 +0100 mat + + * gst/rtsp-server/rtsp-server.c: + #ifdef statements for windows socket creation were missing + +2011-09-06 21:53:46 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From a39eb83 to 11f0cd5 + +2011-09-06 16:07:18 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From 605cd9a to a39eb83 + +2011-08-16 16:39:26 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-08-16 16:07:04 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: use method to access property + +2011-08-16 15:15:19 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: add protocols property + Add a property to configure the allowed protocols in the media created from the + factory. + +2011-08-16 15:03:06 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: add media-configure signal + Add signal to allow the application to configure the media after it was created + from the factory. + +2011-08-16 16:07:04 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: use method to access property + +2011-08-16 15:15:19 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: add protocols property + Add a property to configure the allowed protocols in the media created from the + factory. + +2011-08-16 15:03:06 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: add media-configure signal + Add signal to allow the application to configure the media after it was created + from the factory. + +2011-08-16 14:50:50 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-08-16 13:43:44 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: use media multicast group + +2011-08-16 13:37:50 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.h: + retab some .h + +2011-08-16 13:31:52 +0200 Robert Krakora + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-sdp.h: + sdp: copy and free the server ip address + Copy and free the server ip address to make memory management easier later. + +2011-08-16 13:27:39 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + media-factory: configure multicast in media + +2011-08-16 13:25:16 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add property for multicast group + Add a property to configure the multicast group in the media. + Based on patches from Marc Leeman and Robert Krakora. + +2011-08-16 13:13:36 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: add property for multicast group + Add a property to configure the multicast group in the media factory. + Based on patches from Marc Leeman and Robert Krakora. + +2011-08-16 12:51:44 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: do configuration of transport in one place + Move the configuration of the transport destination address to where we also + configure the other bits. + +2011-08-16 13:43:44 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: use media multicast group + +2011-08-16 13:37:50 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.h: + retab some .h + +2011-08-16 13:31:52 +0200 Robert Krakora + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-sdp.h: + sdp: copy and free the server ip address + Copy and free the server ip address to make memory management easier later. + +2011-08-16 13:27:39 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + media-factory: configure multicast in media + +2011-08-16 13:25:16 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add property for multicast group + Add a property to configure the multicast group in the media. + Based on patches from Marc Leeman and Robert Krakora. + +2011-08-16 13:13:36 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: add property for multicast group + Add a property to configure the multicast group in the media factory. + Based on patches from Marc Leeman and Robert Krakora. + +2011-08-16 12:51:44 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: do configuration of transport in one place + Move the configuration of the transport destination address to where we also + configure the other bits. + +2011-08-16 12:11:59 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-08-16 12:09:48 +0200 Robert Krakora + + * gst/rtsp-server/rtsp-client.c: + client: destroy pipeline on client disconnect with no prior TEARDOWN. + The problem occurs when the client abruptly closes the connection without + issuing a TEARDOWN. The TEARDOWN handler in the rtsp-client.c file of the RTSP + server is where the pipeline gets torn down. Since this handler is not called, + the pipeline remains and is up and running. Subsequent clients get their own + pipelines and if the do not issue TEARDOWNs then those pipelines will also + remain up and running. This is a resource leak. + +2011-08-16 11:53:37 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-06-30 10:13:59 +0200 Emmanuel Pacaud + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: add a "media-constructed" signal to GstRTSPMediaFactory + For example, it can be used to retrieve source elements like appsrc, in a more + convenient way than subclassing get_element. + +2011-08-16 11:12:33 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-08-11 18:07:08 -0700 David Schleef + + * gst/rtsp-server/rtsp-server.c: + rtsp-server: hold on to reference while using object + +2011-08-04 08:59:17 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: use new api + +2011-08-04 08:58:58 +0200 Wim Taymans + + * configure.ac: + configure: use unstable api + +2011-06-27 11:26:26 -0700 David Schleef + + * gst/rtsp-server/rtsp-client.c: + client: fix reference counting + +2011-07-20 17:16:42 +0200 Thijs Vermeir + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + fix compiler warnings about unused variables + +2011-07-19 16:10:39 +0200 Stefan Sauer + + * examples/test-launch.c: + * examples/test-readme.c: + * examples/test-uri.c: + * examples/test-video.c: + examples: tell rtsp uri when ready + +2011-06-23 11:30:14 -0700 David Schleef + + * common: + Automatic update of common submodule + From 69b981f to 605cd9a + +2011-06-13 19:05:57 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: update for buffer API change + +2011-06-07 10:54:26 +0200 Edward Hervey + + * gst/rtsp-server/Makefile.am: + Makefile.am: 0.10 => @GST_MAJORMINOR@ + +2011-06-07 10:59:16 +0200 Edward Hervey + + * gst/rtsp-server/rtsp-media-factory-uri.c: + rtsp-media-factory-uri: GST_PLUGIN_FEATURE_NAME is no longer + +2011-06-07 10:59:03 +0200 Edward Hervey + + * gst/rtsp-server/.gitignore: + .gitignore: 0.10 => 0.11 + +2011-06-07 10:54:26 +0200 Edward Hervey + + * gst/rtsp-server/Makefile.am: + Makefile.am: 0.10 => @GST_MAJORMINOR@ + +2011-05-24 18:26:06 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-05-19 23:00:52 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 9e5bbd5 to 69b981f + +2011-05-18 16:14:10 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From fd35073 to 9e5bbd5 + +2011-05-18 12:27:35 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 46dfcea to fd35073 + +2011-05-17 09:48:13 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media.c: + media: port to new caps API + +2011-05-17 09:45:04 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-05-03 21:13:15 +0200 Fabian Deutsch + + * bindings/vala/gst-rtsp-server-0.10.vapi: + Updated Vala bindings. + Signed-off-by: Fabian Deutsch + +2011-05-03 16:24:28 +0200 Fabian Deutsch + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + Add a signal for newly connected clients. + Signed-off-by: Fabian Deutsch + +2011-05-08 13:15:19 +0200 Alessandro Decina + + * bindings/python/rtspserver.override: + python: override gst_rtsp_media_mapping_add_factory to fix refcounting + +2011-04-26 19:22:50 +0200 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-funnel.c: + * gst/rtsp-server/rtsp-funnel.h: + * gst/rtsp-server/rtsp-media.c: + rtsp-server: port to 0.11 + +2011-04-26 19:14:18 +0200 Wim Taymans + + * common: + add common + +2011-04-26 19:07:13 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + common + configure.ac + +2011-04-24 14:07:11 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From c3cafe1 to 46dfcea + +2011-04-20 11:19:38 +0200 Alessandro Decina + + * bindings/python/Makefile.am: + * bindings/python/rtspserver.defs: + python bindings: wrap GstRTSPMediaFactoryClass vfuncs + +2011-04-20 11:13:56 +0200 Alessandro Decina + + * bindings/python/arg-types.py: + python bindings: add GstRTSPUrlParam + Needed to implement MediaFactory virtual proxies + +2011-04-20 10:19:46 +0200 Alessandro Decina + + * bindings/python/arg-types.py: + python bindings: fix returning GstRTSPUrl types + +2011-04-20 10:17:07 +0200 Alessandro Decina + + * bindings/python/arg-types.py: + python bindings: add arg type for GstRTSPUrl + +2011-04-20 10:16:08 +0200 Alessandro Decina + + * bindings/python/rtspserver.defs: + python bindings: fix the definition of MediaFactory.collect_stream + +2011-04-04 15:59:50 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 1ccbe09 to c3cafe1 + +2011-03-25 22:38:06 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 193b717 to 1ccbe09 + +2011-03-25 14:58:34 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From b77e2bf to 193b717 + +2011-03-25 10:04:57 +0100 Sebastian Dröge + + * Makefile.am: + build: Include lcov.mak to allow test coverage report generation + +2011-03-25 09:35:15 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From d8814b6 to b77e2bf + +2011-03-25 09:11:40 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 6aaa286 to d8814b6 + +2011-03-24 18:51:37 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From 6aec6b9 to 6aaa286 + +2011-03-18 19:34:57 +0100 Luis de Bethencourt + + * autogen.sh: + autogen: wingo signed comment + +2011-03-03 20:38:03 +0100 Miguel Angel Cabrera Moya + + * gst/rtsp-server/rtsp-session-pool.c: + session: use full charset for RTSP session ID + As specified in RFC 2326 section 3.4 use full valid charset to make guessing + session ID more difficult. + https://bugzilla.gnome.org/show_bug.cgi?id=643812 + +2011-03-07 10:23:06 +0100 Sebastian Dröge + + * gst/rtsp-server/Makefile.am: + rtsp-server: Don't install the funnel header + +2011-02-28 18:35:03 +0100 Mark Nauwelaerts + + * common: + Automatic update of common submodule + From 1de7f6a to 6aec6b9 + +2011-02-26 19:58:02 +0000 Tim-Philipp Müller + + * configure.ac: + configure: require core/base 0.10.31 + Needed at least for gst_plugin_feature_rank_compare_func(). + +2011-02-14 12:56:29 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From f94d739 to 1de7f6a + +2011-02-02 15:37:03 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: remove more unused code + +2011-02-02 15:30:45 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: remove duplicate filtering + Remove the duplicate filtering code now that we have a released -good version. + Give a warning instead. + +2011-01-31 17:38:47 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media.c: + media: fix default buffer size + +2011-01-31 17:37:02 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: add property to configure the buffer-size + Add a property to configure the kernel UDP buffer size. + +2011-01-31 17:28:22 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add property to configure kernel buffer sizes + Add a property to configure the kernel UDP buffer size. + +2011-01-26 15:52:54 +0000 Tim-Philipp Müller + + * configure.ac: + configure: set PYGOBJECT_REQ before using it + https://bugzilla.gnome.org/show_bug.cgi?id=640641 + +2011-01-24 11:59:22 +0000 Tim-Philipp Müller + + * docs/Makefile.am: + docs: recursive into sub-directories on 'make upload' + +2011-01-24 11:53:17 +0000 Tim-Philipp Müller + + * docs/libs/gst-rtsp-server-docs.sgml: + * docs/version.entities.in: + docs: mention full version these docs are for, not just major-minor + +2011-01-24 12:07:17 +0100 Wim Taymans + + * configure.ac: + back to development + +=== release 0.10.8 === + +2011-01-24 11:57:12 +0100 Wim Taymans + + * configure.ac: + release 0.10.8 + +2011-01-19 15:29:55 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + rtsp-server: clarify docs a little + +2011-01-13 18:57:15 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: init debug category before starting thread + +2011-01-13 18:40:48 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + auth: add realm to make it more spec compliant + +2011-01-12 18:57:41 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + server: add locking + +2011-01-12 18:33:49 +0100 Wim Taymans + + * examples/test-video.c: + example: improve example docs a little + +2011-01-12 18:26:57 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: ensure the watch has a ref to the server + +2011-01-12 18:24:44 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: simpify channel function + +2011-01-12 18:18:13 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + server: simplify management of channel and source + We don't need to keep around the channel and source objects. Let the mainloop + and the source manage the source and channel respectively. + +2011-01-12 18:17:26 +0100 Wim Taymans + + * Makefile.am: + * configure.ac: + build tests + +2011-01-12 18:16:46 +0100 Wim Taymans + + * tests/.gitignore: + * tests/Makefile.am: + * tests/test-cleanup.c: + tests: add tests directory and cleanup test + +2011-01-12 18:14:48 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-mapping.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session.c: + server: improve debugging in various objects + +2011-01-12 16:38:34 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: chain up to the parent finalize + +2010-09-21 17:04:02 -0300 André Dieb Martins + + * bindings/python/rtspserver-types.defs: + * bindings/python/rtspserver.defs: + * bindings/python/rtspserver.override: + * bindings/python/test.py: + gst-rtsp-server: update python bindings + +2011-01-12 15:37:39 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: use the response from the clientstate + Create the response object only once and store in the client state. + Make all methods use the state response, + +2011-01-12 15:36:22 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: use signal to keep track of clients + Keep track of all the clients that the server creates and remove them when they + fire the 'closed' signal. + +2011-01-12 15:35:51 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: emit signal when closing + +2011-01-12 13:57:09 +0100 Wim Taymans + + * examples/.gitignore: + * examples/Makefile.am: + * examples/test-auth.c: + * examples/test-video.c: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.h: + media: enable per factory authorisations + Allow for adding a GstRTSPAuth on the factory and media level and check + permissions when accessing the factory. + Add hints to the auth methods for future more fine grained authorisation. + Add example application for per factory authentication. + +2011-01-12 13:16:08 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-params.c: + * gst/rtsp-server/rtsp-params.h: + rtsp-server: Pass ClientState structure arround + Pass the collected information for the ongoing request in a GstRTSPClientState + structure that we can then pass around to simplify the method arguments. This + will also be handy when we implement logging functionality. + +2011-01-12 12:07:40 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: add methods to configure authorisation + +2011-01-12 12:07:20 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: unref auth in finalize + +2011-01-12 12:07:04 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: unref auth in finalize + +2011-01-12 11:07:26 +0100 Wim Taymans + + * docs/libs/gst-rtsp-server-docs.sgml: + * docs/libs/gst-rtsp-server-sections.txt: + * docs/libs/gst-rtsp-server.types: + docs: add more docs + +2011-01-12 10:57:08 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + server: separate create and accept + Create separate create and accept methods so that subclasses can create custom + client object. + Configure the server in the client object and prepare for keeping track of + connected clients. + +2011-01-12 10:42:52 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + client: add support for setting the server. + Add support for keeping a ref to the server that started this client + connection. + +2011-01-12 10:41:42 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + auth: fix memleak and add some docs + Fix a memleak of the basic auth token. + Add docs for the helper function + +2011-01-12 00:35:28 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + client: delegate setup of auth to the manager + Delegate the configuration of the authentication tokens to the manager object + when configured. + +2011-01-12 00:17:54 +0100 Wim Taymans + + * examples/test-video.c: + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-auth.c: + * gst/rtsp-server/rtsp-auth.h: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + auth: add authentication object + Add an object that can check the authorization of requests. + Implement basic authentication. + Add example authentication to test-video + +2011-01-12 00:20:36 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + server: move includes back + the includes are needed for sockaddr_in. + +2011-01-11 22:41:12 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + rtsp: move network includes where they are needed + +2011-01-07 23:45:32 +0200 Sreerenj Balachandran + + * gst/rtsp-server/rtsp-media.h: + rtsp-media.h: Minor corrections in comments. + Fixes #638944 + +2011-01-11 15:52:44 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From e572c87 to f94d739 + +2011-01-11 13:01:44 +0100 Edward Hervey + + * .gitignore: + * docs/.gitignore: + * docs/libs/.gitignore: + * examples/.gitignore: + * gst/rtsp-server/.gitignore: + gitignore: updates + +2011-01-11 12:58:39 +0100 Edward Hervey + + * docs/libs/Makefile.am: + docs: We don't build ps/pdf for API reference docs + +2011-01-10 16:39:36 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From ccbaa85 to e572c87 + +2011-01-10 14:56:39 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 46445ad to ccbaa85 + +2011-01-10 15:10:53 +0100 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/fs-funnel.c: + * gst/rtsp-server/fs-funnel.h: + * gst/rtsp-server/rtsp-funnel.c: + * gst/rtsp-server/rtsp-funnel.h: + * gst/rtsp-server/rtsp-media.c: + funnel: rename fsfunnel to rtspfunnel + Rename the funnel to avoid conflicts with the farsight one. + +2011-01-10 13:41:43 +0100 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/fs-funnel.c: + * gst/rtsp-server/fs-funnel.h: + * gst/rtsp-server/rtsp-media.c: + rtsp-media: add and use fsfunnel + Add a copy of fsfunnel to the build because input-selector removed the (broken) + select-all property that we need. + +2011-01-08 01:58:44 +0000 Tim-Philipp Müller + + * gst/rtsp-server/Makefile.am: + gobject-introspection: use PKG_CONFIG_PATH specified at configure time + Use PKG_CONFIG_PATH specified at configure time (if any) as well + for the g-ir-compiler, rather than just assuming the env var has + been set. + +2011-01-08 01:55:06 +0000 Tim-Philipp Müller + + * .gitignore: + * Makefile.am: + * configure.ac: + * m4/Makefile.am: + * m4/codeset.m4: + build: make autotools put all .m4 cruft into m4/ rather than polluting common/m4 + +2011-01-08 01:15:35 +0000 Tim-Philipp Müller + + * configure.ac: + * gst/rtsp-server/Makefile.am: + gobject-introspection: fix g-i build for uninstalled setup + Requires gst-plugins-base git (> 0.10.31.2). + +2011-01-07 11:27:57 +0100 Wim Taymans + + * examples/test-uri.c: + examples: add some more options and comments + +2011-01-07 11:24:39 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + factory-uri: use right property type + +2011-01-05 12:07:42 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + factory-uri: attempt to configure buffer-lists + Attempt to configure buffer lists in the payloader for improved performance. + +2011-01-05 12:06:23 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: attempt to configure bigger UDP buffers + Attempt to configure bigger udp kernel send buffers to avoid overflowing the + send buffers with high bitrate streams. + +2011-01-05 11:26:30 +0100 Jonas Larsson + + * gst/rtsp-server/rtsp-client.c: + client: use the socket length from getsockname + Use the length returned by getsockname to perform the getnameinfo call because + the size can depend on the socket type and platform. + Fixes #638723 + +2010-12-30 12:41:53 +0100 Wim Taymans + + * docs/libs/gst-rtsp-server-docs.sgml: + * docs/libs/gst-rtsp-server-sections.txt: + docs: add uri factory to the docs + +2010-12-30 12:41:31 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.h: + docs: improve docs + +2010-12-29 16:26:41 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + rtsp-server: add support for buffer lists + Add support for sending bufferlists received from appsink. + Fixes #635832 + +2010-12-28 18:35:01 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-sdp.c: + media: make method to retrieve the play range + Make a method to retrieve the playback range so that we can conditionally create + a different range for the SDP and the PLAY requests. + +2010-12-28 18:34:10 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add signal to notify of state changes + +2010-12-28 18:31:26 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.h: + client: cleanup headers + +2010-12-28 12:18:41 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: fix typo + +2010-12-23 18:53:01 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media-factory-uri.h: + factory-uri: add support for gstpay + Add an option to prefer gstpay over decoder + raw payloader. + +2010-12-23 15:58:14 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media-factory-uri.h: + factory-uri: rework the autoplugger. + Rewrite the autoplugger a little so that it prefers to plug demuxers and parsers + before payloaders. + +2010-12-21 17:37:26 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + factory-uri: use better factory filter + Make better payloader filter based on autoplug rank and RTP use case. + +2010-12-20 17:48:41 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From 169462a to 46445ad + +2010-12-18 11:24:48 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: set SO_REUSEADDR before bind + Set the SO_REUSEADDR _before_ bind() to make it actually work. + +2010-12-13 16:58:36 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: emit prepared signal when prepared + Make a 'prepared' signal and emit it when we successfully prepared the element. + This signal can be used to configure the media object after it has been prepared + for streaming. + +2010-12-15 14:58:00 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From 011bcc8 to 169462a + +2010-12-13 16:38:09 +0100 Andy Wingo + + python an optional dependency + * configure.ac: Move up valgrind and g-i checks. Make the python + dependency optional, as it was before. + +2010-12-13 11:43:13 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + common + configure.ac + +2010-12-12 15:48:47 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: update range when active clients changed + When we changed the number of active clients, update the current range + information because we want the second client connecting to a shared resource + continue from where the stream currently. + +2010-12-12 04:06:41 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media-factory-uri.h: + factory-uri: add colorspace and fix pt + Rework the way we pass data to the autoplugger. + When we have raw caps, plug a converter element to make pluggin to raw + payloaders more successful. + Make sure all dynamically plugged payloaders have a unique payload types. + +2010-12-11 18:06:26 +0100 Wim Taymans + + * examples/Makefile.am: + * examples/test-uri.c: + example: add example of the uri factory + +2010-12-11 18:01:53 +0100 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-media-factory-uri.c: + * gst/rtsp-server/rtsp-media-factory-uri.h: + * gst/rtsp-server/rtsp-server.h: + factory-uri: add a factory to stream any URI + Make a factory that uses uridecodebin to decode any uri and autoplug a payloader + when we have one. + +2010-12-11 17:31:44 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: ignore spurious ASYNC_DONE messages + When we are dynamically adding pads, the addition of the udpsrc elements will + trigger an ASYNC_DONE. We have to ignore this because we only want to react to + the real ASYNC_DONE when everything is prerolled. + +2010-12-11 13:41:24 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + media-factory: make lock macro + +2010-12-11 10:53:28 +0100 Edward Hervey + + * gst/rtsp-server/rtsp-client.c: + rtsp-server: Remove unused variable and dead assignment + +2010-12-11 10:49:30 +0100 Edward Hervey + + * examples/test-launch.c: + * examples/test-mp4.c: + * examples/test-ogg.c: + * examples/test-readme.c: + * examples/test-sdp.c: + * examples/test-video.c: + examples: Run gst-indent + +2010-12-11 10:48:42 +0100 Edward Hervey + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-mapping.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-params.c: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session.c: + rtsp-server: Run gst-indent + Since it wasn't using the upstream common previously, there was no + indentation check before commiting. + +2010-12-11 10:48:25 +0100 Edward Hervey + + * gst/rtsp-server/rtsp-media-mapping.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + rtsp-server: Some more doc fixups + +2010-12-07 18:56:03 +0100 Edward Hervey + + * Makefile.am: + Makefile: Add cruft-cleaning support + +2010-12-07 18:52:15 +0100 Edward Hervey + + * Makefile.am: + * configure.ac: + * docs/Makefile.am: + * docs/libs/Makefile.am: + * docs/libs/gst-rtsp-server-docs.sgml: + * docs/libs/gst-rtsp-server-sections.txt: + * docs/libs/gst-rtsp-server.types: + * docs/version.entities.in: + docs: Add gtk-doc build system + +2010-12-07 18:14:39 +0100 Edward Hervey + + * gst/rtsp-server/Makefile.am: + Makefile.am: Use standard GIR make behaviour + +2010-12-07 18:14:22 +0100 Edward Hervey + + * autogen.sh: + * configure.ac: + autogen/configure: Bring more in sync to standard gst module behaviour + +2010-12-06 19:29:53 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: warn and fail when gstrtpbin is not found + +2010-12-06 12:40:30 +0100 Wim Taymans + + * configure.ac: + configure: open 0.11 branch + +2010-12-01 20:00:22 +0100 Edward Hervey + + * .gitmodules: + * common: + Add common submodule + +2010-12-01 19:58:49 +0100 Edward Hervey + + * common/ChangeLog: + * common/Makefile.am: + * common/c-to-xml.py: + * common/check.mak: + * common/coverage/coverage-report-entry.pl: + * common/coverage/coverage-report.pl: + * common/coverage/coverage-report.xsl: + * common/coverage/lcov.mak: + * common/gettext.patch: + * common/glib-gen.mak: + * common/gst-autogen.sh: + * common/gst-xmlinspect.py: + * common/gst.supp: + * common/gstdoc-scangobj: + * common/gtk-doc-plugins.mak: + * common/gtk-doc.mak: + * common/m4/.gitignore: + * common/m4/Makefile.am: + * common/m4/README: + * common/m4/as-ac-expand.m4: + * common/m4/as-auto-alt.m4: + * common/m4/as-compiler-flag.m4: + * common/m4/as-compiler.m4: + * common/m4/as-docbook.m4: + * common/m4/as-libtool-tags.m4: + * common/m4/as-libtool.m4: + * common/m4/as-python.m4: + * common/m4/as-scrub-include.m4: + * common/m4/as-version.m4: + * common/m4/ax_create_stdint_h.m4: + * common/m4/check.m4: + * common/m4/glib-gettext.m4: + * common/m4/gst-arch.m4: + * common/m4/gst-args.m4: + * common/m4/gst-check.m4: + * common/m4/gst-debuginfo.m4: + * common/m4/gst-default.m4: + * common/m4/gst-doc.m4: + * common/m4/gst-error.m4: + * common/m4/gst-feature.m4: + * common/m4/gst-function.m4: + * common/m4/gst-gettext.m4: + * common/m4/gst-glib2.m4: + * common/m4/gst-libxml2.m4: + * common/m4/gst-plugindir.m4: + * common/m4/gst-valgrind.m4: + * common/m4/gtk-doc.m4: + * common/m4/introspection.m4: + * common/m4/pkg.m4: + * common/mangle-tmpl.py: + * common/plugins.xsl: + * common/po.mak: + * common/release.mak: + * common/scangobj-merge.py: + * common/upload.mak: + common: Remove static version + +2010-11-08 17:04:00 +0000 Bastien Nocera + + * common/m4/introspection.m4: + Update introspection.m4 to match usage + +2010-10-30 13:26:12 +0200 Wim Taymans + + * README: + README: update + Remove old stuff from the README + +2010-10-11 11:12:11 +0200 Wim Taymans + + * configure.ac: + back to development + +=== release 0.10.7 === + +2010-10-11 11:05:40 +0200 Wim Taymans + + * configure.ac: + release 0.10.7 + +2010-10-04 17:16:40 +0200 Wim Taymans + + * examples/test-ogg.c: + test-ogg: remove parsers + Remove the parsers, they are not needed anymore as oggdemux now outputs normal + buffers with timestamps. Using the parsers also seems to break things. + +2010-09-23 12:44:18 +0200 Sebastian Pölsterl + + * bindings/vala/gst-rtsp-server-0.10.vapi: + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + Updated Vala bindings + +2010-09-22 23:13:37 +0200 Sebastian Pölsterl + + * common/m4/introspection.m4: + * configure.ac: + * gst/rtsp-server/Makefile.am: + Added initial gobject-introspection support + +2010-09-23 11:32:58 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + media-factory: don't use host for shared hash key + When we generate the key to share made between connections, don't include the + host used to connect so that we can share media even if between clients that + connected with localhost and ones with the ip address. + +2010-09-22 21:16:03 +0100 Tim-Philipp Müller + + * bindings/vala/Makefile.am: + build: fix distcheck + +2010-09-22 18:24:12 +0200 Sebastian Dröge + + * bindings/vala/gst-rtsp-server-0.10.vapi: + * bindings/vala/packages/gst-rtsp-server-0.10.gi: + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + Update Vala bindings + +2010-09-22 18:12:50 +0200 Sebastian Dröge + + * bindings/vala/Makefile.am: + * configure.ac: + Fix configure checks and installation location for Vala bindings + Fixes bug #628676. + +2010-09-22 16:32:30 +0200 Wim Taymans + + * configure.ac: + back to development + +=== release 0.10.6 === + +2010-09-22 16:22:49 +0200 Wim Taymans + + * configure.ac: + configure: release 0.10.6 + +2010-09-22 16:15:56 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: help the compiler a little + +2010-08-24 16:47:30 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-session.c: + media: cleanup media transport before freeing + Cleanup the media transport data before freeing. In particular, remove the qdata + from the rtpsource object. + +2010-08-20 18:17:08 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media-factory: add eos-shutdown property + Add an eos-shutdown property that will send an EOS to the pipeline before + shutting it down. This allows for nice cleanup in case of a muxer. + Fixes #625597 + +2010-08-20 15:58:39 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: use multiudpsink send-duplicates when we can + If we have a new enough multiudpsink with the send-duplicates property, use this + instead of doing our own filtering. Our custom filtering code should eventually + be removed when we can depend on a released -good. + +2010-08-20 13:19:56 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: don't leak destinations + Refactor and cleanup the destinations array when the stream is destroyed. + +2010-08-20 13:09:12 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: don't add udp addresses multiple times + Keep track of the udp addresses we added to udpsink and never add the same udp + destination twice. This avoids duplicate packets when using multicast. + +2010-08-20 10:18:34 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: disable use of SO_LINGER + SO_LINGER cause the client to fail to receive a TEARDOWN message because the + server close()s the connection. + +2010-08-19 18:52:47 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: use 5 second linger period in SO_LINGER + Wait 5 seconds before clearing the send buffers and reseting the connection with + the client when we do a close. This should be enough time to get the message to + the client. + See #622757 + +2010-08-16 12:32:28 +0200 Robert Krakora + + * gst/rtsp-server/rtsp-server.c: + server: use SO_LINGER + SO_LINGER on the socket will make sure that any pending data on the socket is + flushed ASAP and that the socket connection is reset. This makes sure that the + socket can be reused immediately. + Fixes 622757 + +2010-08-16 12:24:50 +0200 Wim Taymans + + * docs/README: + README: add blurb about shared media factories + +2010-08-09 12:56:23 -0700 David Schleef + + * gst/rtsp-server/rtsp-media.c: + Add stdlib.h for atoi() + +2010-05-20 14:33:24 +0100 Tim-Philipp Müller + + * bindings/python/Makefile.am: + * bindings/vala/Makefile.am: + build: distcheck fixes + Fix 'make distcheck', somewhat (it still fails because it tries to + install files into /usr/share/vala/vapi/ irrespective of the + configured prefix). + +2010-05-20 14:09:18 +0100 Tim-Philipp Müller + + * configure.ac: + configure: bump core/base requirements to released version + Makes things less confusing for people. + +2010-04-25 16:35:30 +0100 Tim-Philipp Müller + + * configure.ac: + configure: fail if GStreamer core/base requirements are not met + +2010-04-06 17:08:40 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: improve client cleanups + Make sure the session does not timeout when using TCP. We need to do this + because quicktime player does not send RTCP for some reason in tunneled + mode. + Refactor some cleanup code. + Fixes #612915 + +2010-04-06 17:07:27 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + session: add support for prevent session timeouts + Add an atomix counter to prevent session timeouts when we are, for example, + streaming over TCP. + +2010-04-06 15:45:56 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: fix unlink on session timeouts + When our session times out, make sure we unlink all streams in this + session. + Remove the tunnelid when closing the connection. + +2010-04-06 15:44:45 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-session.c: + session: small cleanups + +2010-04-06 11:13:51 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: handle lost_tunnel callbacks + Handle lost_tunnel callbacks and use it to store the tunnelid back into the + hashtable so that we can reuse it for when the client reopens the POST + socket. + Close the connection after a TEARDOWN. + Make sure or watchid is cleared when the watch is removed. + Fixes #612915 + +2010-03-19 18:03:40 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-sdp.c: + rtsp-server: add more support for multicast + +2010-03-19 15:15:29 +0100 Wim Taymans + + * configure.ac: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: allow configuration of allowed lower transport + +2010-03-16 18:37:18 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-sdp.h: + * gst/rtsp-server/rtsp-server.c: + rtsp: keep track of server ip and ipv6 + Keep track of how the client connected to the server and setup the udp ports + with the same protocol. + Copy the server ip address in the SDP so that clients can send RTCP back to + us. + +2010-03-16 18:34:43 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session.c: + session: indent + +2010-03-16 18:33:23 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: use right size for malloc + +2010-03-10 11:45:30 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + server: comment ipv6 server listening address + +2010-03-10 11:45:06 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: allow for ipv6 sockets + +2010-03-09 13:49:00 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + server: rework server part + Allow setting a bind address, make sure we can deal with ipv6. + Remove the port property and change with the service property. + +2010-03-09 13:44:20 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.h: + media: update comments a little + +2010-03-09 13:43:29 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: make content-base better + Use the URI formatting functions to make a content-base. Also make sure that + there is a trailing / at the end. + +2010-03-09 13:42:50 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: guard against invalid paths + +2010-03-09 13:41:33 +0100 Wim Taymans + + * examples/test-video.c: + test: catch server bind errors + +2010-03-09 10:27:38 +0100 Alessandro Decina + + * gst/rtsp-server/rtsp-media.c: + rtspmedia: emit "unprepared" if _prepare fails. + Emit the unprepared signal if gst_rtsp_media_prepare fails so that the + media object is removed from its factory's cache. + +2010-03-05 19:08:08 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: collect media position when seek completes + +2010-03-05 18:37:17 +0100 Luca Ognibene + + * gst/rtsp-server/rtsp-client.c: + client: call unlink_streams in client finalize + Fixes #599027 + +2010-03-05 18:23:18 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: limit the time to wait to something huge + Avoid waiting forever but limit the timeout to 20 seconds. + +2010-03-05 17:57:08 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-sdp.c: + sdp: reindent and check for prepared status + +2010-03-05 17:51:26 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-session.c: + media: avoid doing _get_state() for state changes + When preparing, use the ASYNC_DONE and ERROR messages in the bus handler to wait + until the media is prerolled or in error. This avoids doing a blocking call of + gst_element_get_state() that can cause lockups when there is an error. + Fixes #611899 + +2010-03-05 16:20:08 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: reindent + +2010-03-05 13:34:15 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + media-factory: better error handling + Improve the error handling a bit. + +2010-03-05 13:31:37 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: rework transport parsing + Rework the transport parsing code so that we can ignore transports we don't + support instead of just picking the first one we can parse. + Configure a (for now hardcoded) destination for multicast transports. + +2010-03-05 13:28:58 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: set multicast sink parameters + Disable loop and automatic multicast join on the udpsink elements. + Add some more debug info. + Reset some state variables in the right place. + Use the right port numbers for multicast. + +2010-03-05 13:27:18 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session.c: + session: handle transport setup correctly + Handle UDP, MCAST and TCP transport negotiation more correctly. + Store the server session SSRC in the transport. + +2010-01-27 18:38:27 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + rtsp-client: implement error_full + Implement error_full to avoid some segfaults when the rtspconnection calls it. + See #608245 + +2009-12-25 18:24:10 +0100 Wim Taymans + + * docs/README: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-server.c: + docs: update docs and comments + +2009-12-25 15:22:23 +0100 Nikolay Ivanov + + * gst/rtsp-server/rtsp-sdp.c: + sdp: make server work better when behind a proxy + +2009-11-21 01:17:25 +0100 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-client.c: + client: dump rtsp message only if debug threshold is higher than GST_LEVEL_LOG + +2009-11-21 19:20:23 +0100 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-mapping.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session.c: + Use GStreamer's debugging subsystem + +2009-11-21 01:00:39 +0100 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-media-factory.c: + server: Set ghost pad active in gst_rtsp_media_factory_collect_streams + +2009-11-05 11:22:44 +0100 Wim Taymans + + * configure.ac: + back to development + +=== release 0.10.5 === + +2009-11-05 11:20:45 +0100 Wim Taymans + + * configure.ac: + release 0.10.5 + +2009-10-14 12:11:31 +0200 Wim Taymans + + * configure.ac: + configure: bump required versions + +2009-10-11 13:57:54 +0200 Luca Ognibene + + * gst/rtsp-server/rtsp-client.c: + client: call weak-unref on client->sessions from finalize + Fixes bug #596305 + +2009-10-09 23:08:18 +0200 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-media.c: + media: Fixed crasher where caps got unref'ed too often + +2009-10-09 16:26:30 +0200 Sebastian Pölsterl + + * configure.ac: + * pkgconfig/.gitignore: + * pkgconfig/Makefile.am: + * pkgconfig/gst-rtsp-server-uninstalled.pc.in: + Added pkg-config file to use gst-rtsp-server uninstalled + +2009-09-11 13:52:27 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: add some docs + +2009-08-24 13:27:00 +0200 Peter Kjellerstedt + + * gst/rtsp-server/rtsp-client.c: + rtsp: Use gst_rtsp_watch_send_message(). + Use gst_rtsp_watch_send_message() since the old API which used + gst_rtsp_watch_queue_message() has been deprecated. + +2009-08-05 11:53:56 +0200 Wim Taymans + + * configure.ac: + back to development + +=== release 0.10.4 === + +2009-08-05 11:44:49 +0200 Wim Taymans + + * configure.ac: + Release 0.10.4 + +2009-07-27 19:42:44 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + rtsp: allocate channels in TCP mode + When the client does not provide us with channels in TCP mode, allocate channels + ourselves. + +2009-07-24 12:49:41 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: don't crash when tunnelid is missing + When a clients tries to open an HTTP tunnel but fails to provide a tunnelid, + don't crash but return an error response to the client. + Fixes #589489 + +2009-07-13 11:31:23 +0200 Sebastian Pölsterl + + * bindings/vala/gst-rtsp-server-0.10.vapi: + * bindings/vala/packages/gst-rtsp-server-0.10.gi: + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + bindings: update vala bindings with new method + +2009-06-30 21:27:53 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + sessionpool: add function to filter sessions + Add generic function to retrieve/remove sessions. + +2009-06-22 18:57:25 +0100 Tim-Philipp Müller + + * configure.ac: + configure: bump core/base requirements to release + +2009-06-18 16:05:18 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: fix indentation + +2009-06-14 23:12:13 +0200 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-media.c: + Unref pipeline and set it to NULL. Set stream's caps to NULL, otherwise we unref it too often. + +2009-06-13 16:05:02 +0200 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-media.c: + set state and remove elements of media in for loop + +2009-06-13 14:38:39 +0200 Sebastian + + * bindings/vala/gst-rtsp-server-0.10.vapi: + * bindings/vala/packages/gst-rtsp-server-0.10.gi: + Added gst_rtsp_media_remove_elements function to Vala bindings + +2009-06-13 14:38:20 +0200 Sebastian + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + Added gst_rtsp_media_remove_elements function + +2009-06-12 22:22:40 +0200 Sebastian + + * gst/rtsp-server/rtsp-media.c: + Don't use name for gstrtpbin so we can add multiple instances to the pipeline + +2009-06-12 19:28:04 +0200 Sebastian Pölsterl + + * bindings/vala/gst-rtsp-server-0.10.vapi: + * bindings/vala/packages/gst-rtsp-server-0.10.gi: + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + Updated Vala bindings + +2009-06-12 18:05:30 +0200 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + Added vmethod unprepare to GstRTSPMedia + The default implementation sets the state of the pipeline to GST_STATE_NULL + +2009-06-12 17:51:44 +0200 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + Made collect_streams function public + +2009-06-12 17:45:29 +0200 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + Added vmethod create_pipeline to GstRTSPMediaFactory + The pipeline is created in this method and the GstRTSPMedia's element is added to it + +2009-06-11 11:27:47 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: use g_source_destroy() + We need to use g_source_destroy() because we might have added the source to a + different main context than the default one. + +2009-06-10 00:01:07 +0200 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-params.c: + * gst/rtsp-server/rtsp-params.h: + rtsp: prepare for handling GET/SET_PARAMETER + Add helper functions to handle GET/SET_PARAMETER. Reply with an error when there + is a body now. + Fix return codes of handlers. + +2009-06-04 19:20:26 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: don't leak session pads + +2009-06-04 18:32:15 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: clean up the messages a bit + +2009-06-03 12:13:21 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-sdp.c: + sdp: warn and skip streams without media + +2009-05-30 14:38:34 +0200 Sebastian Pölsterl + + * bindings/vala/gst-rtsp-server-0.10.vapi: + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + vala: Fixed typo in header file of RTSPMediaStream + +2009-05-27 11:15:22 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: fix message + Fix a debug message + Make dumping RTCP stats configurable + +2009-05-26 19:20:07 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: be less verbose and leak less + +2009-05-26 19:05:07 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: don't leak the destination address + +2009-05-26 19:01:10 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + rtsp: use RTCP to keep the session alive + Use the RTCP rtcp-from stats field to find the associated session and use this + to keep the session alive. + +2009-05-26 17:27:07 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-session.c: + session: add 5sec to the real session timeout + Allow the session to live 5sec longer before really timing out. This should give + clients some extra time to keep the session active. + +2009-05-26 17:25:59 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: replay OK to GET/SET_PARAMETER + Some clients (vlc) use GET/SET_PARAMETER to keep the TCP session open. Make it + so that we return OK for those requests. + +2009-05-26 11:42:41 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: keep track of active transports + Keep track of which transport is active to avoid closing the connection too + soon. + Remove the destination transport also when going to NULL. + Print some stats about the SDES and other RTCP messages we receive from the + clients. + +2009-05-24 20:00:19 +0200 Wim Taymans + + * examples/.gitignore: + * examples/Makefile.am: + * examples/test-sdp.c: + example: add SDP relay example + +2009-05-24 19:56:45 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: also count active TCP connections + +2009-05-24 19:34:52 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + rtsp: add support for dynamic elements + Add support for dynamic elements. + Don't set live pipelines back to paused. + +2009-05-24 19:33:22 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-sdp.c: + sdp: don't add encoding name when absent in caps + +2009-05-23 16:30:55 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: warn when we can't do RTP-Info + +2009-05-23 16:18:04 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + factory: factor out the stream construction + +2009-05-23 16:17:02 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: only add RTP-Info when we have the info + Only add RTP-Info for a stream when we can get the seqnum and timestamp from the + depayloader. + +2009-05-17 14:04:31 +0200 Wim Taymans + + * configure.ac: + back to development + +=== release 0.10.3 === + +2009-05-17 13:59:10 +0200 Wim Taymans + + * configure.ac: + release: 0.10.3 + - Fixes a bug where it put the wrong verion in pkgconfig + - Link RTP and RTCP sources + +2009-05-15 17:58:44 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: link the RTP udpsrc to the session manager + Link the RTP udpsrc and the appsrc to the session manager so that they don't + shut down when the client sends a packet to open firewalls. + +2009-05-15 17:10:44 +0200 Sebastian Pölsterl + + * pkgconfig/gst-rtsp-server.pc.in: + Don't use hard-coded version number in pkg-config file + +2009-05-11 10:51:47 +0200 Wim Taymans + + * configure.ac: + back to development + +=== release 0.10.2 === + +2009-05-11 10:50:31 +0200 Wim Taymans + + * configure.ac: + release 0.10.2 + +2009-05-11 10:38:44 +0200 Wim Taymans + + * .gitignore: + * common/m4/.gitignore: + * examples/.gitignore: + * pkgconfig/.gitignore: + add some .gitignore files + +2009-04-29 17:24:46 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: seek to key frames + +2009-04-21 22:44:05 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + media: emit the unprepared signal by id + Emit the unprepared signal by id instead of name and set the media as + reused. + +2009-04-21 22:23:54 +0200 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-media.c: + Set pipeline's state to NULL no matter if the media is reusable and emit unprepared signal in gst_rtsp_media_unprepare + +2009-04-18 16:10:59 +0200 Sebastian Pölsterl + + * gst/rtsp-server/rtsp-server.c: + Added finalize function to GstRTPSPServer to unref session pool and media mapping + +2009-04-17 21:13:07 +0200 Sebastian Pölsterl + + * bindings/vala/gst-rtsp-server-0.10.vapi: + * bindings/vala/packages/gst-rtsp-server-0.10.gi: + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + Updated vala bindings + +2009-04-14 23:38:58 +0200 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + server: use appsink and appsrc with the API + Use the appsink/appsrc API instead of the signals for higher + performance. + +2009-04-14 23:38:15 +0200 Wim Taymans + + * examples/test-ogg.c: + tests: set the payload type correctly + +2009-04-03 22:46:22 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + factory: connect to the unprepare signal + Connect to the unprepare signal for non-reusable media so that we can remove + them from the cache. + +2009-04-03 22:45:57 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: add signal to notify of unprepare + +2009-04-03 22:22:30 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + media: more work on making the media shared + Add a reusable flag to medias, indicating that they can be reused after a state + change to NULL. + Small cleanups. + +2009-04-03 19:47:38 +0200 Wim Taymans + + * examples/test-readme.c: + examples: mark the example as shared for testing + +2009-04-03 19:44:37 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + client: support shared media + Always perform the state actions even if the target state of the pipeline is + already correct, we still want to add/remove the transports when we are dealing + with shared media. + Keep a counter of the number of active transports for a media so that we can use + this to perform a state change when needed. + Perform a state change of the pipeline only when the first transport was added + or when there are no active transports. + +2009-04-03 09:03:59 +0200 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + client: fix refcounting crasher + Don't need to remove the weak refs in the finalize methods, they are already + removed in the dispose. + Don't register the callback with a DestroyNofity. + +2009-04-01 01:01:46 +0100 Tim-Philipp Müller + + * gst/rtsp-server/rtsp-client.c: + Fix rtsp client refcount management in TCP mode. + Don't unref a client ref we never had. Fixes an unref + of an already-free client object after a client + teardown request for me. + +2009-04-01 00:45:17 +0100 Tim-Philipp Müller + + * gst/rtsp-server/rtsp-session.c: + docs: fix typo in API docs + +2009-03-13 15:57:42 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + More seeking fixes. + Keep the udp sources in playing even if we go to paused. unlock the sources when + we shut down. + Add some more debug info. + Only seek when we need to. + Keep track of the position when we go to paused. + +2009-03-12 20:32:14 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + Add beginnings of seeking. + Parse the Range header and perform a seek on the pipeline for the requested + position. It's disabled currently until I figure out what's going wrong. + +2009-03-12 20:31:22 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + allow pause requests for now. + -- + +2009-03-11 20:03:06 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + Remove weak ref on the session in teardown + We need to remove our weakref from the session when we do a teardown because + else we close the TCP connection prematurely. + +2009-03-11 19:38:06 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-session-pool.c: + Do some more session cleanup + Make session timeout kill the TCP connection that currently watches the + session. + Remove the client timeout property. + +2009-03-11 16:45:12 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + Add TCP transports + Use appsrc and appsink to send and receive RTP/RTCP packets in the TCP + connection. + +2009-03-11 16:39:20 +0100 Wim Taymans + + * examples/Makefile.am: + * examples/test-launch.c: + Add example server that takes launch lines + Add an example server that streams any -launch line. + +2009-03-06 19:34:14 +0100 Wim Taymans + + * examples/test-readme.c: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + Add support for live streams + Add support for live streams and ranges + Start on handling TCP data transfer. + +2009-03-04 16:33:59 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + Free the pipeline before other things + --- + +2009-03-04 16:33:21 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + Only free the pending tunnel if there is one + -- + +2009-03-04 12:44:01 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media.c: + rtsp-server: Add support for tunneling + Add support for tunneling over HTTP. + Use new connection methods to retrieve the url. + Dispatch messages based on the message type instead of blindly + assuming it's always a request. + Keep track of the watch id so that we can remove it later. + Set the media pipeline to NULL before unreffing the pipeline. + +2009-02-19 15:53:50 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + Fix for channel -> watch rename in gstreamer + Rename the RTSPChannel to RTSPWatch and remove an unused variable. + +2009-02-18 18:57:31 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + Use ASYNC RTSP io + Use the async RTSP channels instead of spawning a new thread for each client. + If a sessionid is specified in a request, fail if we don't have the session. + +2009-02-18 17:49:03 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + Add better debug info + Add some better debug info. + +2009-02-13 20:00:34 +0100 Wim Taymans + + * examples/test-video.c: + Time out sessions + Add support for session timeouts in the example. + +2009-02-13 19:58:17 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + Pass GTimeVal around for performance reasons + Get the current time only once and pass it around so that sessions don't have to + get the current time anymore. + Add experimental support for a GSource that dispatches when the session needs to + be cleaned up. + +2009-02-13 19:56:01 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + Add better support for session timeouts + Add a method to request the number of milliseconds when a session will timeout. + +2009-02-13 19:54:18 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + Add suport for RTP manager monitoring + Add the first stage in monitoring the rtp manager. + Make sure we don't update the state to something we don't want. + +2009-02-13 19:52:05 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + Add support for session keepalive + Get and update the session timeout for all requests. get the session as early as + possible. + +2009-02-13 16:39:36 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + Handle media bus messages + Handle media bus messages in a custom mainloop and dispatch them to the + RTSPMedia objects. Let the default implementation handle some common messages. + +2009-02-13 12:57:45 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session.c: + Some more session timeout handling + Move the session header setting code to a central place so that we always add + the timeout parameter too. + Handle timeouts by running the session cleanup code. + Stop media before cleaning up. + +2009-02-10 16:24:13 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + Add timeout property + Add a timeout property ot the client and make the other properties into GObject + properties. + +2009-02-10 16:21:17 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session-pool.c: + Use getters and setters in property code + Use the getters and setters for the timeout property instead of locking + ourselves. + +2009-02-04 20:13:32 +0100 Wim Taymans + + Merge branch 'master' of git+ssh://git.collabora.co.uk/git/gst-rtsp-server + +2009-02-04 20:10:39 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + Add more timeout stuff + Add method to check if a session is expired. + Add method to perform cleanup on a session pool. + +2009-02-04 19:52:50 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + Add beginnings of session timeouts and limits + Add the timeout value to the Session header for unusual timeout values. + Allow us to configure a limit to the amount of active sessions in a pool. Set a + limit on the amount of retry we do after a sessionid collision. + Add properties to the sessionid and the timeout of a session. Keep track of + creation time and last access time for sessions. + +2009-02-04 17:00:42 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + Cleanup of sessions and more + Fix the refcounting of media and sessions in the client. Properly clean up the + session data when the client performs a teardown. + Add Server header to responses. + Allow for multiple uri setups in one session. + Add Range header to the PLAY response and add the range attribute to the SDP + message. + Fix the session pool remove method, it used the wrong key in the hashtable. Also + give the ownership of the sessionid to the session object. + +2009-02-04 09:57:55 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + Rename a variable + Rename the 'server_port' variable to simply 'port'. + +2009-02-03 19:32:38 +0100 Wim Taymans + + * configure.ac: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + Rework the way we handle transports for streams + Make the media accept an array of transports for the streams that we have + configured for the play/pause requests. + Implement server states for a client and its media. + Require 0.10.22.1 (git HEAD) of gstreamer. + +2009-01-31 19:50:33 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory.c: + Drop const from functions dealing with urls + Drop const from GstRTSPUrl stuff because the .h files in gst-plugins-base don't + have the right const in them. + +2009-01-30 17:06:26 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-sdp.c: + Fix various leaks + Fix some leaks. + +2009-01-30 16:24:10 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + More cleanups + Don't keep a reference to the GstRTSPMedia in the stream. + Free more things when freeing the GstRTSPMedia. + +2009-01-30 14:53:28 +0100 Wim Taymans + + * docs/README: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + More docs and small cleanups + Add some more docs and update the README + Cleanup some method names. + Remove an unneeded idx field in the GstRTSPMediaStream + +2009-01-30 13:24:04 +0100 Wim Taymans + + * docs/README: + * examples/Makefile.am: + * examples/test-readme.c: + Add a README and more example code + Add a README file that contains a small introduction on how to use the server + along with the example code explained in the readme. + +2009-01-30 11:06:31 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-server.c: + Fix some leaks and change default port + Fix some memory leaks by setting the udpsrc elements to the unlocked state after + we finished the initial preroll. If we keep them locked, setting the pipeline to + NULL will not stop and clean up the sources correctly. + Change the default RTSP port to 8554 aka the official alternative RTSP port. + +2009-01-29 18:55:22 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + Cleanups to the session object + Remove some unneeded variables in the session state of a stream such as the + owner media and the server transport. + Get the configuration of a media stream in a session based on the media_stream + in the original object instead of our cached index. + Free more data in the finalize method. + +2009-01-29 18:51:02 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + Cleanups and reuse media from DESCRIBE + Handle thread create errors. + Rename some internal methods to better match what they actually do. + Handle misconfiguration of session_pool and media_mapping gracefully. + Cache the DESCRIBE media and uri in the client connection and reuse them when + we receive a SETUP request in the same connection for the same uri. + Cleanup the client connection object. + +2009-01-29 17:20:27 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + Add shared properties to media and factory + Add the shared property to media. + Implement some simple caching in the factory depending on if the media is shared + or not. + +2009-01-29 17:19:21 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + Add a little comment + Add some comment about the content-base header. + +2009-01-29 13:31:27 +0100 Wim Taymans + + * examples/Makefile.am: + * examples/main.c: + * examples/test-mp4.c: + * examples/test-ogg.c: + * examples/test-video.c: + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-sdp.c: + * gst/rtsp-server/rtsp-sdp.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + Reorganize things, prepare for media sharing + Added various other test server examples + Move the SDP message generation to a separate helper. + Refactor common code for finding the session. + Add content-base for realplayer compatibility + Clean up request uris before processing for better vlc compatibility. + Move prerolling and pipeline construction to the RTSPMedia object. + Use multiudpsink for future pipeline reuse. + +2009-01-30 11:23:57 +0100 Wim Taymans + + * configure.ac: + Back to development + Back to 0.10.1.1 + +=== release 0.10.1 === + +2009-01-30 11:20:18 +0100 Wim Taymans + + * configure.ac: + Make 0.10.1 release + Release 0.10.1 + +2009-01-29 15:19:01 +0100 Wim Taymans + + * bindings/vala/Makefile.am: + Fix make dist + Add more directories and files to the dist. + +2009-01-24 14:34:35 +0100 Sebastian Pölsterl + + * bindings/python/Makefile.am: + * bindings/python/rtspserver.override: + Fixed compile error of python bindings + +2009-01-23 21:03:53 +0100 Sebastian Pölsterl + + * bindings/vala/gst-rtsp-server-0.10.vapi: + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + Marked values as nullable accordingly + +2009-01-23 20:31:11 +0100 Sebastian Pölsterl + + * bindings/vala/gst-rtsp-server-0.10.vapi: + * bindings/vala/packages/gst-rtsp-server-0.10.excludes: + * bindings/vala/packages/gst-rtsp-server-0.10.gi: + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + Updated Vala bindings + +2009-01-22 18:35:17 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-mapping.c: + * gst/rtsp-server/rtsp-media-mapping.h: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-session-pool.h: + Cleanups and doc updates + Add some more documentation and do some minor cleanups here and there. + +2009-01-22 17:58:19 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + More improvements + Rename GstRTSPMediaBin to GstRTSPMedia + Parse the request url into a GstRTSPUri object and pass this object to the + various handlers and methods that require the uri. + +2009-01-22 16:54:07 +0100 Wim Taymans + + * examples/main.c: + Update example + Add some more docs and remove some old code from the example. + +2009-01-22 16:53:16 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + Handle state change failures better + Handle state change failures better when changing the state of the pipeline to + determine the SDP. + +2009-01-22 16:51:08 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + Make element creation more extendible + Add get_element vmethod to the default MediaFactory so that subclasses can just + override that method and still use the default logic for making a MediaBin from + that. + +2009-01-22 15:33:29 +0100 Wim Taymans + + * examples/main.c: + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + * gst/rtsp-server/rtsp-media-mapping.c: + * gst/rtsp-server/rtsp-media-mapping.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + Make the server handle arbitrary pipelines + Make GstMediaFactory an object that can instantiate GstMediaBin objects. + The GstMediaBin object has a handle to a bin with elements and to a list of + GstMediaStream objects that this bin produces. + Add GstMediaMapper that can map url mountpoints to GstMediaFactory objects along + with methods to register and remove those mappings. + Add methods and a property to GstRTSPServer to manage the GstMediaMapper object + used by the server instance. + Modify the example application so that it shows how to create custom pipelines + attached to a specific mount point. + Various misc cleanps. + +2009-01-20 19:47:07 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + Allow setting a custom media factory for a server + +2009-01-20 19:46:21 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + Allow setting a custom media factory for a client. + +2009-01-20 19:45:28 +0100 Wim Taymans + + * gst/rtsp-server/Makefile.am: + Add Makefile entry for the media factory + +2009-01-20 19:44:45 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media-factory.c: + * gst/rtsp-server/rtsp-media-factory.h: + Add media factory to map urls to media pipeline objects. + +2009-01-20 19:43:47 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + Add comments. Remove unused field + +2009-01-20 19:41:53 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + Allow custom session pools to override the session id allocation algorithms Add some comments. + +2009-01-20 19:40:42 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session.h: + Add some comments. + +2009-01-20 13:57:47 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + Move the connection code in one place Add some comments + +2009-01-20 13:19:36 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + Make vmethod to create and accept new clients. Add some docs. + +2009-01-19 19:36:23 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + Make more properties configurable in the server. Expose the GIOChannel and GSource better to allow for more customisations. + +2009-01-19 19:34:29 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + Name the parameters more appropriately. + +2009-01-19 19:32:28 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-session-pool.c: + Do some more cleanup of the session pool. + +2009-01-08 16:28:24 +0100 Wim Taymans + + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-client.c: + Check if return value of gst_rtsp_session_get_media is not NULL + +2009-01-08 15:02:42 +0100 Wim Taymans + + * gst/rtsp-server/Makefile.am: + Install rtsp-session and rtsp-session-pool headers + +2009-01-08 14:57:55 +0100 Wim Taymans + + * .gitignore: + * Makefile.am: + * acinclude.m4: + * bindings/python/Makefile.am: + * bindings/python/arg-types.py: + * bindings/python/codegen/Makefile.am: + * bindings/python/codegen/__init__.py: + * bindings/python/codegen/argtypes.py: + * bindings/python/codegen/code-coverage.py: + * bindings/python/codegen/codegen.py: + * bindings/python/codegen/definitions.py: + * bindings/python/codegen/defsparser.py: + * bindings/python/codegen/docextract.py: + * bindings/python/codegen/docgen.py: + * bindings/python/codegen/fileprefix.override: + * bindings/python/codegen/fileprefixmodule.c: + * bindings/python/codegen/h2def.py: + * bindings/python/codegen/mergedefs.py: + * bindings/python/codegen/mkskel.py: + * bindings/python/codegen/override.py: + * bindings/python/codegen/reversewrapper.py: + * bindings/python/codegen/scmexpr.py: + * bindings/python/rtspserver-types.defs: + * bindings/python/rtspserver.defs: + * bindings/python/rtspserver.override: + * bindings/python/rtspservermodule.c: + * configure.ac: + Add python bindings. + +2009-01-08 14:53:47 +0100 Wim Taymans + + * bindings/Makefile.am: + * configure.ac: + Don't go into python dir when requirements for python bindings are missing + +2009-01-08 14:49:57 +0100 Wim Taymans + + * bindings/Makefile.am: + * bindings/vala/Makefile.am: + * configure.ac: + Install Vala bindings if vala is available + +2008-12-12 16:22:02 +0100 Sebastian Pölsterl + + * bindings/vala/gst-rtsp-server-0.10.deps: + * bindings/vala/gst-rtsp-server-0.10.vapi: + * bindings/vala/gst-rtsp-server.vapi: + * bindings/vala/packages/gst-rtsp-server-0.10.deps: + * bindings/vala/packages/gst-rtsp-server-0.10.excludes: + * bindings/vala/packages/gst-rtsp-server-0.10.files: + * bindings/vala/packages/gst-rtsp-server-0.10.gi: + * bindings/vala/packages/gst-rtsp-server-0.10.metadata: + * bindings/vala/packages/gst-rtsp-server-0.10.namespace: + * bindings/vala/packages/gst-rtsp-server.deps: + * bindings/vala/packages/gst-rtsp-server.excludes: + * bindings/vala/packages/gst-rtsp-server.files: + * bindings/vala/packages/gst-rtsp-server.gi: + * bindings/vala/packages/gst-rtsp-server.metadata: + * bindings/vala/packages/gst-rtsp-server.namespace: + Regenerated Vala bindings + +2008-12-08 13:19:40 +0100 Sebastian Pölsterl + + * bindings/vala/gst-rtsp-server.vapi: + * bindings/vala/packages/gst-rtsp-server.metadata: + Fixed typo in included headers for vala bindings + +2009-01-08 14:42:10 +0100 Wim Taymans + + * Makefile.am: + * configure.ac: + * pkgconfig/Makefile.am: + * pkgconfig/gst-rtsp-server.pc.in: + Added pkgconfig file + +2008-11-30 23:57:26 +0100 Sebastian Pölsterl + + * bindings/vala/gst-rtsp-server.vapi: + * bindings/vala/packages/gst-rtsp-server.excludes: + * bindings/vala/packages/gst-rtsp-server.gi: + * bindings/vala/packages/gst-rtsp-server.metadata: + Adjusted included headersfor Vala bindings. Ignore rtsp-url-compat.h + +2008-11-30 23:41:20 +0100 Sebastian Pölsterl + + * bindings/vala/gst-rtsp-server.vapi: + * bindings/vala/packages/gst-rtsp-server.deps: + * bindings/vala/packages/gst-rtsp-server.files: + * bindings/vala/packages/gst-rtsp-server.gi: + * bindings/vala/packages/gst-rtsp-server.metadata: + * bindings/vala/packages/gst-rtsp-server.namespace: + Added Vala bindings + +2008-10-25 23:36:16 +0200 Alessandro Decina + + * gst/rtsp-server/rtsp-session.c: + Change an obviously wrong return FALSE to return NULL; (cherry picked from commit 56d4fb48030db3ae45f3f0e60b29b36f3134322b) + +2008-11-13 19:43:10 +0100 Sebastian Pölsterl + + * examples/Makefile.am: + * gst/rtsp-server/Makefile.am: + Put GStreamer version in library name + +2009-01-08 13:51:26 +0100 Wim Taymans + + * examples/Makefile.am: + * gst/rtsp-server/Makefile.am: + Fix some issues to pass distcheck + +2009-01-08 13:41:33 +0100 Wim Taymans + + * gst/rtsp-server/rtsp-server.c: + Added port property to GstRTSPServer class. + +2009-01-08 13:18:55 +0100 Wim Taymans + + * Makefile.am: + * autogen.sh: + * configure.ac: + * examples/Makefile.am: + * examples/main.c: + * gst/Makefile.am: + * gst/rtsp-server/Makefile.am: + * gst/rtsp-server/rtsp-client.c: + * gst/rtsp-server/rtsp-client.h: + * gst/rtsp-server/rtsp-media.c: + * gst/rtsp-server/rtsp-media.h: + * gst/rtsp-server/rtsp-server.c: + * gst/rtsp-server/rtsp-server.h: + * gst/rtsp-server/rtsp-session-pool.c: + * gst/rtsp-server/rtsp-session-pool.h: + * gst/rtsp-server/rtsp-session.c: + * gst/rtsp-server/rtsp-session.h: + * src/Makefile.am: + * src/main.c: + * src/rtsp-client.c: + * src/rtsp-client.h: + * src/rtsp-media.c: + * src/rtsp-media.h: + * src/rtsp-server.c: + * src/rtsp-server.h: + * src/rtsp-session-pool.c: + * src/rtsp-session-pool.h: + * src/rtsp-session.c: + * src/rtsp-session.h: + Split in library and example program + +2008-11-10 20:59:35 +0100 Sebastian Pölsterl + + * src/rtsp-client.h: + Removed obsolete variable + +2008-11-10 21:03:15 +0100 Sebastian Pölsterl + + * src/rtsp-client.c: + * src/rtsp-client.h: + Removed pipeline variable GstRTSPClient, because it's only used in one function + +2009-01-08 11:22:58 +0100 Wim Taymans + + * src/rtsp-media.c: + Set the payload types for the different payloaders. Maybe this shoulde be done automatically instead. + +2008-10-23 12:23:27 +0200 Wim Taymans + + * src/rtsp-session.c: + Initialize some more vars. + +2008-10-23 12:14:55 +0200 Wim Taymans + + * src/rtsp-session.c: + Initialize variable to avoid compiler warning. + +2008-10-09 13:30:47 +0100 Simon McVittie + + * .gitignore: + Add a reasonable generic .gitignore + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..2099840 --- /dev/null +++ b/INSTALL @@ -0,0 +1,370 @@ +Installation Instructions +************************* + +Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, +Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell command `./configure && make && make install' +should configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + HP-UX `make' updates targets which have the same time stamps as +their prerequisites, which makes it generally unusable when shipped +generated files such as `configure' are involved. Use GNU `make' +instead. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf limitation. Until the limitation is lifted, you can use +this workaround: + + CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..100b512 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,79 @@ +DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc + +SUBDIRS = \ + gst \ + common \ + examples \ + pkgconfig \ + tests + +DIST_SUBDIRS = $(SUBDIRS) + +EXTRA_DIST = \ + ChangeLog autogen.sh depcomp \ + AUTHORS COPYING NEWS README RELEASE REQUIREMENTS \ + gst-rtsp-server.spec docs/design/gst-rtp-server-design \ + gst-rtsp-server.doap + +ACLOCAL_AMFLAGS = -I m4 -I common/m4 + +DISTCLEANFILES = _stdint.h gst-rtsp-server.spec + +include $(top_srcdir)/common/release.mak +include $(top_srcdir)/common/po.mak + +include $(top_srcdir)/common/coverage/lcov.mak + +check-valgrind: + cd tests/check && make check-valgrind + +if HAVE_CHECK +check-torture: + cd tests/check && make torture +else +check-torture: + true +endif + +# cruft: plugins that have been merged or moved or renamed +CRUFT_FILES = \ + $(top_builddir)/common/shave \ + $(top_builddir)/common/shave-libtool \ + $(top_builddir)/common/m4/codeset.m4 \ + $(top_builddir)/common/m4/gettext.m4 \ + $(top_builddir)/common/m4/glibc2.m4 \ + $(top_builddir)/common/m4/glibc21.m4 \ + $(top_builddir)/common/m4/iconv.m4 \ + $(top_builddir)/common/m4/intdiv0.m4 \ + $(top_builddir)/common/m4/intl.m4 \ + $(top_builddir)/common/m4/intldir.m4 \ + $(top_builddir)/common/m4/intlmacosx.m4 \ + $(top_builddir)/common/m4/intmax.m4 \ + $(top_builddir)/common/m4/inttypes-pri.m4 \ + $(top_builddir)/common/m4/inttypes_h.m4 \ + $(top_builddir)/common/m4/lcmessage.m4 \ + $(top_builddir)/common/m4/lib-ld.m4 \ + $(top_builddir)/common/m4/lib-link.m4 \ + $(top_builddir)/common/m4/lib-prefix.m4 \ + $(top_builddir)/common/m4/libtool.m4 \ + $(top_builddir)/common/m4/lock.m4 \ + $(top_builddir)/common/m4/longlong.m4 \ + $(top_builddir)/common/m4/ltoptions.m4 \ + $(top_builddir)/common/m4/ltsugar.m4 \ + $(top_builddir)/common/m4/ltversion.m4 \ + $(top_builddir)/common/m4/lt~obsolete.m4 \ + $(top_builddir)/common/m4/nls.m4 \ + $(top_builddir)/common/m4/po.m4 \ + $(top_builddir)/common/m4/printf-posix.m4 \ + $(top_builddir)/common/m4/progtest.m4 \ + $(top_builddir)/common/m4/size_max.m4 \ + $(top_builddir)/common/m4/stdint_h.m4 \ + $(top_builddir)/common/m4/uintmax_t.m4 \ + $(top_builddir)/common/m4/visibility.m4 \ + $(top_builddir)/common/m4/wchar_t.m4 \ + $(top_builddir)/common/m4/wint_t.m4 \ + $(top_builddir)/common/m4/xsize.m4 + +include $(top_srcdir)/common/cruft.mak + +all-local: check-cruft diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..cc265ee --- /dev/null +++ b/NEWS @@ -0,0 +1,2 @@ +This is GStreamer RTSP Server 1.4.5 + diff --git a/README b/README new file mode 100644 index 0000000..2373730 --- /dev/null +++ b/README @@ -0,0 +1,4 @@ +gst-rtsp-server is a library ion top of GStreamer for building an RTSP server + +There are some examples in the examples/ directory and more comprehensive +documentation in docs/README. diff --git a/RELEASE b/RELEASE new file mode 100644 index 0000000..f5876ce --- /dev/null +++ b/RELEASE @@ -0,0 +1,69 @@ + +Release notes for GStreamer RTSP Server Library 1.4.5 + +The GStreamer team is pleased to announce a bugfix release of the stable +1.4 release series. The 1.4 release series is adding new features on top +of the 1.2 series and is part of the API and ABI-stable 1.x release +series of the GStreamer multimedia framework that contains new features. +The 1.4.x bugfix releases only contain important bugfixes compared to 1.4.0. + + +Binaries for Android, iOS, Mac OS X and Windows are provided by the +GStreamer project for this release. + + +The 1.x series is a stable series targeted at end users. It is not API +or ABI compatible with the 0.10.x series. It can, however, be installed +in parallel with the 0.10.x series and will not affect an existing +0.10.x installation. + + +The stable 1.4.x release series is API and ABI compatible with 1.0.x and +any other 1.x release series in the future. Compared to 1.0.x it contains +some new features and more intrusive changes that were considered too +risky as a bugfix. + + + + +Bugs fixed in this release + + * 739481 : rtsp-stream: leaks srtp decoder when leaving rtpbin + +==== Download ==== + +You can find source releases of gst-rtsp-server in the download +directory: http://gstreamer.freedesktop.org/src/gst-rtsp-server/ + +The git repository and details how to clone it can be found at +http://cgit.freedesktop.org/gstreamer/gst-rtsp-server/ + +==== Homepage ==== + +The project's website is http://gstreamer.freedesktop.org/ + +==== Support and Bugs ==== + +We use GNOME's bugzilla for bug reports and feature requests: +http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer + +Please submit patches via bugzilla as well. + +For help and support, please subscribe to and send questions to the +gstreamer-devel mailing list (see below for details). + +There is also a #gstreamer IRC channel on the Freenode IRC network. + +==== Developers ==== + +GStreamer is stored in Git, hosted at git.freedesktop.org, and can be cloned +from there (see link above). + +Interested developers of the core library, plugins, and applications should +subscribe to the gstreamer-devel list. + + +Contributors to this release + + * Aleix Conchillo Flaqué +  \ No newline at end of file diff --git a/REQUIREMENTS b/REQUIREMENTS new file mode 100644 index 0000000..14e4172 --- /dev/null +++ b/REQUIREMENTS @@ -0,0 +1,3 @@ +You need to have GStreamer. You can use an installed version of +GStreamer or from its build dir. + diff --git a/TODO b/TODO new file mode 100644 index 0000000..53d7d1c --- /dev/null +++ b/TODO @@ -0,0 +1,3 @@ + + - use a config file to configure the server + - error recovery diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..267b167 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,113 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + + +test -n "$srcdir" || srcdir=`dirname "$0"` +test -n "$srcdir" || srcdir=. + +olddir=`pwd` +cd "$srcdir" + +DIE=0 +package=gst-rtsp +srcfile=gst/rtsp-server/rtsp-server.c + +# Make sure we have common +if test ! -f common/gst-autogen.sh; +then + echo "+ Setting up common submodule" + git submodule init +fi +git submodule update + +# source helper functions +if test ! -f common/gst-autogen.sh; +then + echo There is something wrong with your source tree. + echo You are missing common/gst-autogen.sh + exit 1 +fi +. common/gst-autogen.sh + +# install pre-commit hook for doing clean commits +if test ! \( -x .git/hooks/pre-commit -a -L .git/hooks/pre-commit \); +then + rm -f .git/hooks/pre-commit + ln -s ../../common/hooks/pre-commit.hook .git/hooks/pre-commit +fi + +NOCONFIGURE=1 +CONFIGURE_DEF_OPT='--enable-maintainer-mode --enable-gtk-doc' + +autogen_options $@ + +printf "+ check for build tools" +if test ! -z "$NOCHECK"; then echo ": skipped version checks"; else echo; fi +version_check "autoconf" "$AUTOCONF autoconf autoconf270 autoconf269 autoconf268 " \ + "ftp://ftp.gnu.org/pub/gnu/autoconf/" 2 68 || DIE=1 +version_check "automake" "$AUTOMAKE automake automake-1.11" \ + "ftp://ftp.gnu.org/pub/gnu/automake/" 1 11 || DIE=1 +#version_check "autopoint" "autopoint" \ +# "ftp://ftp.gnu.org/pub/gnu/gettext/" 0 17 || DIE=1 +version_check "libtoolize" "$LIBTOOLIZE libtoolize glibtoolize" \ + "ftp://ftp.gnu.org/pub/gnu/libtool/" 2 2 6 || DIE=1 +version_check "pkg-config" "" \ + "http://www.freedesktop.org/software/pkgconfig" 0 8 0 || DIE=1 + +die_check $DIE + +aclocal_check || DIE=1 +autoheader_check || DIE=1 + +die_check $DIE + +# if no arguments specified then this will be printed +if test -z "$*" && test -z "$NOCONFIGURE"; then + echo "+ checking for autogen.sh options" + echo " This autogen script will automatically run ./configure as:" + echo " ./configure $CONFIGURE_DEF_OPT" + echo " To pass any additional options, please specify them on the $0" + echo " command line." +fi + +toplevel_check $srcfile + +# autopoint +#if test -d po ; then +# tool_run "$autopoint" "--force" +#fi + +# aclocal +# if test -f acinclude.m4; then rm acinclude.m4; fi + +tool_run "$libtoolize" "--copy --force" +tool_run "$aclocal" "-I m4 -I common/m4 $ACLOCAL_FLAGS" +tool_run "$autoheader" + +# touch the stamp-h.in build stamp so we don't re-run autoheader in maintainer mode +echo timestamp > stamp-h.in 2> /dev/null + +tool_run "$autoconf" +debug "automake: $automake" +tool_run "$automake" "--add-missing --copy" + +test -n "$NOCONFIGURE" && { + echo "+ skipping configure stage for package $package, as requested." + echo "+ autogen.sh done." + exit 0 +} + +cd "$olddir" + +echo "+ running configure ... " +test ! -z "$CONFIGURE_DEF_OPT" && echo " default flags: $CONFIGURE_DEF_OPT" +test ! -z "$CONFIGURE_EXT_OPT" && echo " external flags: $CONFIGURE_EXT_OPT" +echo + +echo "$srcdir/configure" $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT +"$srcdir/configure" $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT || { + echo " configure failed" + exit 1 +} + +echo "Now type 'make' to compile $package." diff --git a/common/ChangeLog b/common/ChangeLog new file mode 100644 index 0000000..92d0d25 --- /dev/null +++ b/common/ChangeLog @@ -0,0 +1,1712 @@ +2008-12-17 Edward Hervey + + * gst.supp: + And yet another variation of the GstAudioFilter leak. + +2008-12-15 Sebastian Dröge + + Patch by: Roland Illig + + * m4/gst-parser.m4: + Fix AG_GST_BISON_CHECK to handle version numbers with more than + two components (i.e. 2.4.1). Fixes bug #564507. + +2008-12-14 Edward Hervey + + * gst.supp: + And yet another variant of the GstAudioFilter leak. + +2008-12-13 Edward Hervey + + * gst.supp: + Added variants of leaks of dynamic pad templates created in + GstAudioFilter. + Add conditional jump triggered by getaddrinfo (maybe glibc-2.9). + +2008-12-12 Edward Hervey + + * gst.supp: + Fix leak in GIO called by gnomevfs. Nothing we can do about this. + +2008-12-12 Edward Hervey + + * gst.supp: + Added another suppression for dynamic pad templates, in this case + GstAudioFilter. + Added suppression for PangoLanguage which can never be freed + according to the Pango API. + +2008-12-12 Edward Hervey + + * gst.supp: + A whole bunch of suppressions detected on latest gentoo ~amd64. + Make some existing suppressions more generic (for subtle dependecy + code changes). + Added suppressions for glibc-2.9. + Added suppressions for new variants of ALSA leaks. + Added suppressions for a series of leaks in plugins registrations due + to some pad templates' caps calculated at runtime. + Added suppressions for variants of some leaks in pango/fontconfig. + Added suppressions for leak in gstffmpegcsp.c (nothing we can do + about it, but will only exist once). + +2008-12-04 Sebastian Dröge + + * m4/gst-plugin-docs.m4: + Remove the check if $have_gtk_doc equals yes as it's not defined + and $enable_gtk_doc should be good enough. + Also this restores the build of the plugin documentation. + +2008-12-01 Mark Nauwelaerts + + * gst.supp: + Add suppression variant for Ubuntu Hardy x86/64bit. + +2008-12-01 Stefan Kost + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Simplily uninstall rule. Its closer to upstream and fixes #150331. + +2008-11-29 Sebastian Dröge + + * m4/glib-gettext.m4: + Update glib-gettext.m4 from latest stable GLib release. + +2008-11-29 Sebastian Dröge + + Patch by: Cygwin Ports maintainer + + + * gettext.patch: + Update the gettext patch for use with gettext 0.17 which is + required to build with libtool 2.2 because of conflicts. + First part of bug #556091. + +2008-11-29 Sebastian Dröge + + * m4/gtk-doc.m4: + * m4/pkg.m4: + Update gtk-doc and pkg-config m4 macros from their latest releases. + +2008-11-20 Michael Smith + + * m4/as-objc.m4: + Fix objective C test macro when none of the compilers are found at all. + +2008-10-30 Stefan Kost + + * gtk-doc.mak: + Also cp the entities here to all xinlcude based docs (workaround for + not being able to set up a search path). + +2008-10-17 Jan Schmidt + + * gtk-doc.mak: + Don't clobber the real registry cache file when + building docs. + +2008-10-07 Jan Schmidt - Sun Microsystems + + * m4/gst-error.m4: + Also disable the bogus "loop not entered at top" warnings appearing on Sparc Forte builds. + +2008-10-06 Stefan Kost + + * gtk-doc.mak: + Apply the same fix as below to gtk-doc.mak. Somehow did not end up in + CVS. + +2008-09-05 David Schleef + + * gtk-doc-plugins.mak: Fix the check for gtkdoc-rebase: don't + pass the 'which' error back to make. This fix is more specific + than what is in upstream. + +2008-09-05 David Schleef + + * gtk-doc.mak: Fix the check for gtkdoc-rebase: don't pass the + 'which' error back to make. This fix is more specific than + what is in upstream. + +2008-09-04 Stefan Kost + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Get closer to upstream makefiles. Don't install index.sgml twice. Call + gtkdoc-rebase (if exists). + +2008-08-21 Stefan Kost + + * gtk-doc-plugins.mak: + Revert $(top_builddir) -> $(builddir) change of rev. 1.39 as there is + no variable called builddir. + +2008-07-31 Mark Nauwelaerts + + * gst.supp: + Add suppressions for Ubunty Hardy x86/64bit, similar to earlier + versions and 32bit variant. + +2008-07-31 Sebastian Dröge + + * m4/gst-feature.m4: + Remove GST_DISABLE_(ENUMTYPES|INDEX|URI). + +2008-07-21 Tim-Philipp Müller + + * m4/gst-error.m4:: + When checking for GST_ERROR_CXXFLAGS, check each compiler flag + individually, not all together. + +2008-07-20 Tim-Philipp Müller + + * m4/gst-parser.m4:: + Fix bison version number detection for older --version + output format (as bison 1.28 on OSX 10.4 outputs). + Fixes #543853. + +2008-07-12 Stefan Kost + + * plugins.xsl: + Split refsect2 also here to make "Element Pads" subtitle visible. + +2008-07-08 Sebastian Dröge + + * m4/gst-error.m4: + Add compiler flags to warn if declarations after statements or + variable length arrays are used. These are C99/GCC extensions and + are not supported by some compilers we want to support. + +2008-07-02 Mark Nauwelaerts + + * gtk-doc-plugins.mak: + Only clean doc maintainer stamps in maintainer-clean. Fixes #539977. + +2008-06-20 Sebastian Dröge + + * gstdoc-scangobj: + Always use format strings for printf-like functions, even if they just + print a string. Fixes bug #536981. + +2008-06-20 Sebastian Dröge + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Include CFLAGS and LDFLAGS in GTKDOC_CFLAGS and GTKDOC_LDFLAGS, + otherwise the values passed to configure are ignored. + Fixes bug #536978. + +2008-06-05 Tim-Philipp Müller + + * m4/gst-error.m4: + Add -fno-strict-aliasing when compiling with -Werror, to work around + warnings caused by G_LOCK with recent GLib versions (2.16.x) (#316221). + +2008-06-05 Jan Schmidt + + * gtk-doc.mak: + Don't copy html/*.png files unless they don't already exist + in the destdir. Fixes distcheck failure caused by permissions + problems trying to copy a file into the destdir when it already + exists. + +2008-05-28 Stefan Kost + + * plugins.xsl: + The class was not shown in plugin docs. Fix typo in changelog below. + +2008-05-22 Jan Schmidt + + * gstdoc-scangobj: + Emit warnings if one of the GTypes we're expecting is 0 + when scanning. + +2008-05-21 Felipe Contreras + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Fix installing png images when gtk-doc is disabled. + +2008-05-21 Felipe Contreras + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Fix make clean when gtk-doc is disabled and other cleanups. + +2008-05-17 Jan Schmidt + + * gtk-doc-plugins.mak: + Be more quiet when the files don't yet exist. + +2008-05-16 Jan Schmidt + + * gstdoc-scangobj: + Add a mechanism for adding 'implicitly created' GTypes into the + scan, allowing for documenting plugin-private base classes that + provide signals or properties for public elements. + + * gtk-doc-plugins.mak: + Use $(builddir) instead of $(top_builddir) in a few places - there's + no need to hard code 'docs/plugins' as the only useable path. + +2008-05-14 Peter Kjellerstedt + + * m4/gst-feature.m4: + Report plug-ins without external dependencies that will not be built + even when the name of the plug-in is a substring of another plug-in, + e.g., goom vs. goom2k1. + +2008-05-14 Tim-Philipp Müller + + * gst.supp: + Add suppression for glibc bug on gutsy/x86-64 + +2008-05-12 Stefan Kost + + * plugins.xsl: + Improve the layout of the caps, but splitting them on ";". + +2008-05-09 Sebastian Dröge + + Patch by: Brian Cameron + + * m4/gst-default.m4: + Don't set the default audio sink to the default visualizer. + Fixes bug #532295. + +2008-05-07 Tim-Philipp Müller + + * check.mak: (help): + Document GST_CHECKS environment variable in checks 'make help'. + +2008-05-06 Sebastian Dröge + + Patch by: Marc-Andre Lureau + + * scangobj-merge.py: + Don't depend on Twisted just for the OrderedDict but implement our + own ordered dictionary class. Fixes bug #531577. + +2008-04-23 Edward Hervey + + * gst.supp: + Re-arrange latest suppressions. + Add all known suppressions for ubuntu hardy. Same as for older + ubuntus, but with different codepaths. + +2008-04-22 Edward Hervey + + * gst.supp: Make tls leak suppression a bit more generic. + +2008-04-22 Edward Hervey + + * gst.supp: Fix ommission in latest commit. + Make tls leak suppression more generic in order to cover more + distributions (and hopefully also future distributions). + +2008-04-22 Edward Hervey + + * gst.supp: Add suppressions for Hardy. + They're just the newer versions of similar suppressions we had + for the previous versions of ubuntu. + +2008-04-15 Sebastian Dröge + + * Makefile.am: + * m4/Makefile.am: + Dist all files in common. Fixes bug #527984. + +2008-04-14 Tim-Philipp Müller + + * m4/gst-function.m4: + Rename AC_CACHE_VAL cache-ids to contain '_cv_' in order to make + autoconf-2.62 complain less. + +2008-04-13 Tim-Philipp Müller + + * m4/gst-args.m4: + * m4/gst-valgrind.m4: + Bump valgrind requirement to 3.0 (which was released in August 2005). + Fixes #489269. Also, check for version >=REQ and not >REQ. + +2008-04-09 Tim-Philipp Müller + + * m4/gst-default.m4: + Add --with-default-{audiosink|audiosrc|videosink|videosrc|visualizer} + configure switches (#519417). + +2008-04-03 Tim-Philipp Müller + + * m4/gst-args.m4: + Add --disable-foo switch for dependency-less plugins (#525586). + +2008-04-01 Sebastian Dröge + + * m4/gst-parser.m4: + Unconditionally require flex 2.5.31 and bison 1.875. + +2008-03-23 Sebastian Dröge + + * m4/gst-arch.m4: + amd64/x86_64 allows unaligned memory access too. + +2008-03-21 Sebastian Dröge + + * m4/gst-dowhile.m4: + Add macro that checks if the compiler supports do {} while (0) + macros and define HAVE_DOWHILE_MACROS if it does. This is + needed by glib/gmacros.h to use something else than + if (1) else for G_STMT_START/END when compling C++, which + causes compiler warnings because of ambigious else with g++ 4.3. + +2008-03-21 Sebastian Dröge + + * m4/gst-plugin-docs.m4: + * mangle-tmpl.py: + Don't depend on PyXML and use only XML modules that are shipped + with python. Fixes bug #519635. + +2008-03-07 Edward Hervey + + * m4/gtk-doc.m4: (GTK_DOC_CHECK): + The previous commit to this file by Stefan Kost mentionned checking for + SED, but NOT checking for gtkdoc-check (wth is that doing there ??). + Therefore, removing the check for gtkdoc-check + +2008-03-03 David Schleef + + * m4/ax_create_stdint_h.m4: Oops, checked in the wrong copy of + this file. (Update from upstream) + +2008-03-03 David Schleef + + * m4/ax_create_stdint_h.m4: Update from upstream. Fixes a bug + compiling with MSVC. + +2008-03-03 Edward Hervey + + * m4/pkg.m4: + Allow override of pkg-config results, as proposed by configure --help. + This is in fact just a backport from upstream pkg.m4. + Fixes #518892 + +2008-03-03 Peter Kjellerstedt + + * ChangeLog: + Changelog surgery of my previous commit to add bugzilla reference. + * m4/gst-args.m4: + Add AG_GST_CHECK_PLUGIN and AG_GST_DISABLE_PLUGIN to make it easier + to include and exclude plug-ins without external references, i.e., + plug-ins listed in GST_PLUGINS_SELECTED. (#498222) + +2008-03-03 Sebastian Dröge + + * gst.supp: + Add another glibc suppression. + +2008-02-29 Peter Kjellerstedt + + * m4/gst-feature.m4: + Make the comment before defines generated via AG_GST_CHECK_FEATURE + look nicer. (#498222) + +2008-02-26 Jan Schmidt + + * m4/Makefile.am: + * m4/as-gcc-inline-assembly.m4: + Add Dave Schleef's GCC inline assembly detection macro + for using in gst-plugins-good in the goom 2k4 plugin. + +2008-02-25 Andy Wingo + + * gst-autogen.sh: Instead of only passing certain arguments to + configure, pass anything that we didn't handle. Much friendlier. + Fixes #34412. + +2008-02-23 Jan Schmidt + + * m4/gst-error.m4: + Store the detected compiler flags into ERROR_CFLAGS rather than + ERROR_CXXFLAGS, and use the macro that checks the C compiler, not + the C++ one. + +2008-02-23 Tim-Philipp Müller + + * m4/gst-error.m4: + Reflow checks for additional warning flags so they're not + nested, which fixes the result reporting in the configure + output. + +2008-02-22 Tim-Philipp Müller + + * m4/as-compiler-flag.m4: + Add AS_CXX_COMPILER_FLAG + + * m4/gst-error.m4: + Add AG_GST_SET_ERROR_CXXFLAGS (Forte bits need testing) + +2008-02-22 Tim-Philipp Müller + + * gtk-doc-plugins.mak: + Add 'check-inspected-versions' target; this helps identify + files that should have been removed or where the version + number should (ideally) be updated before a release + (which doesn't happen automatically if the releaser doesn't + build that plugin locally). Not adding at a distcheck hook + yet though, because it's not really that important and would + probably also be a problem on buildbots. + +2008-02-22 Sebastian Dröge + + * gst.supp: + Add even more glibc 2.7 suppressions. + +2008-02-22 Sebastian Dröge + + * gst.supp: + Add another suppression for GLib caching some values after + the first call. + +2008-02-12 Sebastian Dröge + + Patch by: + Tim Mooney + + * m4/gst-error.m4: + Use no%E_MACRO_REDEFINED on Solaris to prevent compiler warnings. + Fixes bug #515905. + +2008-02-11 Sebastian Dröge + + * gst.supp: + Add a few more glibc 2.7 suppressions to make the avisubtitle unit + test valgrind clean. Fixes bug #515703. + +2008-02-08 Stefan Kost + + * ChangeLog: + Changelog surgery for last commit. + +2008-02-08 Stefan Kost + + * m4/gtk-doc.m4: + Conditionally check for SED. Also sync a bit with upstream macro. + +2008-02-08 Stefan Kost + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Use '$(SED)' instead of 'sed'. Don't use -i for in-place as its gnu + only, move to a temp file instead. + +2008-02-06 Stefan Kost + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + As our docs are versioned, we need to patch the index.sgml file to have + correct paths there, unless we also want to fork gtk-doc's xsl (which + we don't). This hopefully fixes xrefs between modules. + +2008-02-02 Sebastian Dröge + + * m4/gst-feature.m4: + Use printf instead of echo as "echo -e" isn't POSIX and doesn't work + with strict POSIX shells like tcsh or dash and also not every platform + has a /bin/echo that supports it. + +2008-01-24 Stefan Kost + + * ChangeLog: + ChangeLog surgery. + + * gstdoc-scangobj: + Sync the object scanner with gtk-doc fixes. Update args and hierarchy + files. + +2008-01-20 Sebastian Dröge + + * check.mak: + * coverage/lcov.mak: + * gtk-doc-plugins.mak: + * release.mak: + Use $(MAKE) instead of make to fix the build if GNU make is called + something else on the system. + + * m4/as-docbook.m4: + Fix path for docbook.xsl if we have no /etc/xml/catalog and add a + docbook-xsl search path for FreeBSD. + +2008-01-18 Sebastian Dröge + + * gst.supp: + Add a suppression for a glibc bug: + http://valgrind.org/docs/manual/faq.html#faq.exit_errors> + +2008-01-18 Sebastian Dröge + + * gst.supp: + Add some more glibc 2.7 suppressions and make the GLib suppressions + for the home/tmp/etc directory caching a bit more generic. + +2008-01-18 Sebastian Dröge + + * gst.supp: + Add some glibc 2.7 supressions as found on Debian/unstable. + +2008-01-14 Jan Schmidt + + * download-translations: + Apparently I have problems with leaving things commented out when + I edit shell scripts. + +2008-01-12 Jan Schmidt + + * download-translations: + Remove bash-isms + +2008-01-12 Jan Schmidt + + * check-exports: + Restore the cleanup rm of our tmp file which I didn't mean to leave + commented out. + +2008-01-12 Jan Schmidt + + * check-exports: + Fixes to make check-export work on both Solaris and Linux + + * m4/gst-error.m4: + Disable extra warning category (argument mismatch) as an error + on Forte, as it prevents the libcheck fail_if macros from compiling. + + * win32.mak: + Substitute the GStreamer version so things will keep working in 0.11 + +2008-01-11 Tim-Philipp Müller + + Patch by: Peter Kjellerstedt + + * m4/gst-glib2.m4: + * m4/gst-libxml2.m4: + Improve/fix output from configure if either glib-2.0 or + libxml2 are not installed (#498222). + +2008-01-09 Stefan Kost + + * coverage/lcov.mak: + Update coverage make-rules: use them conditionaly, use libtool mode + and use lcov to cleanup. + +2007-12-18 Sebastian Dröge + + * glib-gen.mak: + Also use #include "header" instead of #include
for the + headers that were used to generate the source files for the same + reason as below. + + Remove whitespace before #include. + +2007-12-18 Sebastian Dröge + + * glib-gen.mak: + Use #include "header" instead of #include
for the generated + enum C files as the file will always be in the same directory and + some compilers seem to be a bit strict about that unless . is added + to the include path. + + Include all headers that were used to generate the source files in + the C file as they're used there. + +2007-12-17 Tim-Philipp Müller + + * win32.mak: (win32), (win32defs), (win32crlf): + Make check for CR LF in Visual C++ 6.0 project files + work, based on patch by David Schleef (#496722, #393626). + +2007-12-17 Tim-Philipp Müller + + * Makefile.am: + Don't forget to dist the new win32.mak. + +2007-12-17 Tim-Philipp Müller + + * win32.mak: (win32), (win32defs): + Move common win32 Makefile foo into this new file. + +2007-12-15 Stefan Kost + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + We should have never forked this that much :/. + +2007-12-13 Tim-Philipp Müller + + * check-exports: + Fix build on the ppc64 build bot. + +2007-12-13 Tim-Philipp Müller + + * check-exports: + Suppress more unintentional exports (too much hassle to rename them, + since the win32 project files would need changing too). + +2007-12-12 Tim-Philipp Müller + + * Makefile.am: + check-exports should be disted. + +2007-12-12 Tim-Philipp Müller + + * check-exports: + Add quick'n'dirty script to check the exported symbols of a library + against the symbols in the corresponding .def file (#493983). Based + on script by Ole André Vadla Ravnås. + +2007-11-06 Jan Schmidt + + * gtk-doc-plugins.mak: + Fix distcheck by making sure the types files are treated like the + other gtkdoc-scangobj generated files. + +2007-09-21 Sebastian Dröge + + * m4/gst-args.m4: + Let the AG_GST_ARG_ENABLE_EXPERIMENTAL macro default to disable + building of experimental plugins. Nobody uses it yet and the + --enable--experimental stuff from gst-plugins-good defaults to + disable too. + +2007-09-06 Tim-Philipp Müller + + * gtk-doc-plugins.mak: + Just use the normal 'check' target and avoid a circular + dependency. + +2007-09-06 Tim-Philipp Müller + + * gtk-doc-plugins.mak: + Add rule to error out if .hierarchy file contains tabs. + +2007-08-20 Tim-Philipp Müller + + * download-translations: + * po.mak: + If there are new languages, they need to be added to po/LINGUAS. + +2007-08-20 Tim-Philipp Müller + + * download-translations: + * po.mak: + Fix up 'download-po' a bit, so that we find new translations + for languages that aren't in our po/LINGUAS file yet too. + +2007-07-16 Jan Schmidt + + * gst.supp: + Add a suppression for GLib caching the tmp dir seen on an + Ubuntu Feisty system. + +2007-07-13 Jan Schmidt + + * m4/gst-feature.m4: + If we want to use 'echo -e', call /bin/echo instead of the shell's + since -e is a bash extension, and our /bin/sh might not be being + provided by bash. + +2007-07-01 Thomas Vander Stichele + + * po.mak: + Translation project has moved. Also, no idea how this used to + work given that we weren't downloading a .po file. + +2007-06-25 Stefan Kost + + * gst-xmlinspect.py: + * plugins.xsl: + Also extract element caps for plugin-docs. Fixes parts of #117692. + +2007-06-21 Tim-Philipp Müller + + Patch by: Andreas Schwab + + * m4/gst-feature.m4: + Fix quoting (#449493). + +2007-06-10 Sebastian Dröge + + * m4/gst-parser.m4: + Only generate the parser if bison >= 1.875 _and_ flex >= 2.5.31 is + installed and use pre-generated sources otherwise. Fixes bug #444820. + +2007-05-11 Michael Smith + + * gst.supp: + Suppression variant for our good friend the TLS leak, this time for + Ubuntu Feisty/x86. + +2007-05-09 Tim-Philipp Müller + + * gtk-doc-plugins.mak: + Fix make distcheck again; change some spaces to tabs in makefile. + +2007-04-29 Thomas Vander Stichele + + * gtk-doc-plugins.mak (-module): + Error out when the html build step gives warnings, so they get + fixed properly. + +2007-04-23 Stefan Kost + + * m4/gst-feature.m4: + Add macro AG_GST_PARSE_SUBSYSTEM_DISABLES that checks the defines in + the configuration header and AC_DEFINES the setings. + +2007-04-19 Sebastian Dröge + + Patch by: Vincent Torri + + * m4/gst-parser.m4: + Put the AC_MSG_RESULT output in brackets to get it properly written to + the terminal. + +2007-04-18 Sebastian Dröge + + * m4/gst-parser.m4: + Check for flex >= 2.5.31 and set GENERATE_PARSER if we have at least + that version. Otherwise use pre-generated parser sources as we can't + raise the required flex version. HAVE_MT_SAVE_FLEX is obsolete now + as we use a new enough flex version anyway. First part of #349180 + +2007-04-10 Thomas Vander Stichele + + * m4/gst-check.m4: + Allow pre-setting the GST(PB)_TOOLS/PLUGINS_DIR variables to help + builds against older GStreamer. + +2007-03-25 Sebastian Dröge + + * m4/gst-parser.m4: + Fix the flex version check. It ignored the micro version before. + +2007-03-09 Jan Schmidt + + * check.mak: + Use the same timeout when generating valgrind suppressions as + running the valgrind test. + + * gst.supp: + Add some more suppressions and stuff. + +2007-03-08 Jan Schmidt + + * check.mak: + Make sure GSlice is disabled when building suppressions too. + + * gst.supp: + Add around *850* lines of suppressions for one-time initialisations + inside libasound and gconf/bonobo/ORBit. I feel so dirty. + +2007-03-07 Jan Schmidt + + * gst.supp: + add a suppression for this GConf flup on the FC5 buildbot. + +2007-03-06 Jan Schmidt + + * gst.supp: + Make the suppression a little more generic, to catch the FC5 + backtrace too. + +2007-03-06 Jan Schmidt + + * gst.supp: + Add a suppression for libcdio 0.76. It leaks an internal struct + when the CD-ROM device is not accessible. + +2007-02-28 Thomas Vander Stichele + + * m4/gst-arch.m4: + Move a line that was in the wrong macro + +2007-02-28 Thomas Vander Stichele + + * m4/gst.m4: + Add + * m4/gst-arch.m4: + * m4/gst-args.m4: + * m4/gst-check.m4: + * m4/gst-debuginfo.m4: + * m4/gst-default.m4: + * m4/gst-doc.m4: + * m4/gst-error.m4: + * m4/gst-feature.m4: + * m4/gst-function.m4: + * m4/gst-gettext.m4: + * m4/gst-glib2.m4: + * m4/gst-libxml2.m4: + * m4/gst-parser.m4: + * m4/gst-plugin-docs.m4: + * m4/gst-plugindir.m4: + * m4/gst-valgrind.m4: + * m4/gst-x11.m4: + Convert all macros to use AG_GST style so we can properly warn + when they're missing if configure.ac calls AG_GST_INIT + Will require update in all GStreamer modules. + +2007-02-11 Stefan Kost + + * m4/gst-args.m4: + Remove 'enable' from configure switch description as this leads to + confusing lines like "disable enable builing ...". + * m4/gst-feature.m4: + Fix comment to sound less horrible. + +2007-02-07 Tim-Philipp Müller + + Patch by: Will Newton + + * m4/gst-check.m4: + Use $PKG_CONFIG rather than pkg-config directly, the one in our path + might not be the one we want, like when cross-compiling. Also, other + macros such as PKG_CHECK_MODULES use $PKG_CONFIG, so we should + probably too just for consistency. Fixes #405288. + +2007-01-08 Tim-Philipp Müller + + * m4/gst-parser.m4: + Need to use double square brackets again so m4 doesn't remove them + (fixes #378931). + + * m4/gst-args.m4: + Use double square brackets here as well, for the same reason. + +2007-01-05 Tim-Philipp Müller + + * m4/gst-parser.m4: + Use 'sed' rather than 'tr' to strip trailing letters from version + numbers, since 'tr' might not be available and we know sed is + (#378931). + +2006-10-21 Tim-Philipp Müller + + * check.mak: + Increase default timeout under valgrind, 60 is just too short and + some tests take a bit longer these days and not everyone has a + beefy machine. + +2006-09-29 Michael Smith + + * gst.supp: + More suppressions for edgy. + +2006-09-28 Jan Schmidt + + * m4/gst-glib2.m4: + Use gmodule-no-export-2.0.pc instead of gmodule-2.0.pc - we neither + want nor need --export-dynamic (which ends up making us export a bunch + of unneeded symbols) + +2006-09-14 Tim-Philipp Müller + + * gst.supp: + Some suppressions for the more recent ld.so in ubuntu edgy. + +2006-08-23 Tim-Philipp Müller + + * gst.supp: + Shorten function trail so the suppression works on + my ubuntu dapper system with core cvs as well. + +2006-07-28 Jan Schmidt + + * gst.supp: + Extra suppressions from my Ubuntu x86_64 machine + +2006-07-24 Tim-Philipp Müller + + Patch by: Frederic Peters + + * m4/gst-parser.m4: + Need to double square brackets in .m4 files. Should fix bison + version detection with version numbers like 1.23a (#348354). + +2006-07-24 Jan Schmidt + + * check.mak: + Valgrind fails to find tests written in tests/check/ directly (rather + than a subdir) - because valgrind gets run with a filename that + doesn't contain a relative path, it goes searching /usr/bin instead. + Run with ./.... to make things work either way. + + * gtk-doc-plugins.mak: + Add $(top_builddir)/src as a place to look for plugins + when building too, since that's where gst-template keeps things + +2006-07-23 Stefan Kost + + Patch by: Frederic Peters + + * m4/gst-parser.m4: + Fix bison detection (#348354) + +2006-07-21 Stefan Kost + + * m4/gst-parser.m4: + check for bison and flex + +2006-07-13 Thomas Vander Stichele + + * m4/gst-plugin-docs.m4: + remove the configure argument for enabling plugin doc build; + having gtk-doc enabled and pyxml present is enough of a trigger + +2006-07-03 Thomas Vander Stichele + + * coverage/lcov.mak: + fix up rules to work with gst-python as well + run "make lcov" to test and generate the reports + run "make lcov-reset" to redo it after that + +2006-07-02 Thomas Vander Stichele + + * Makefile.am: + * check.mak: + add an inspect target that inspects every element feature, + so we can have that added for coverage + * coverage/lcov.mak: + add support for lcov + +2006-07-02 Thomas Vander Stichele + + * m4/gst-args.m4: + when building with gcov, reset CFLAGS and friends to O0 + +2006-07-02 Thomas Vander Stichele + + * m4/gst-args.m4: + Find the gcov that matches the gcc version + Only allow gcov if we use gcc + +2006-07-02 Thomas Vander Stichele + + * Makefile.am: + * coverage/coverage-report-entry.pl: + * coverage/coverage-report.pl: + * coverage/coverage-report.xsl: + copy coverage reporting files from dbus + +2006-07-01 Thomas Vander Stichele + + * m4/gst-args.m4: + libtool strips gcov's -f flags, so libgcov does not get + linked in. Setting GCOV_LIBS with -lgcov fixes libtool's + stripping + also show what pkg-config-path we set + +2006-06-22 Tim-Philipp Müller + + Patch by: Peter Kjellerstedt + + * m4/gst-feature.m4: + Show list of plugins without external dependencies that + will not be built as well (#344136). + +2006-06-15 Tim-Philipp Müller + + * m4/gst-plugin-docs.m4: + add GST_PLUGIN_DOCS, which checks for everything needed + to build the plugin docs (namely gtk-doc and pyxml); also + adds a new --enable-plugin-docs configure switch; will + set ENABLE_PLUGIN_DOCS conditional for use in Makefile.am + files (see #344039). + +2006-06-11 Thomas Vander Stichele + + * m4/gst-check.m4: + add GST_PKG_CHECK_MODULES, which in the normal case of checking + for a dependency lib for a plug-in only needs two arguments + to do the right thing. + * m4/gst-feature.m4: + clean up output a little of feature checking; also deal with + non-plug-in feature checks + * m4/Makefile.am: + * m4/gst-gstreamer.m4: + remove this file; it's a useless check + +2006-06-06 Thomas Vander Stichele + + * m4/gst-arch.m4: + add PPC64 so we can have separate structure sizes for it + +2006-06-05 Edward Hervey + + * gtk-doc.mak: + Check for the proper .devhelp2 file to remove. + +2006-05-31 Thomas Vander Stichele + + * gtk-doc.mak: + allow a magic variable to suppress errors from docbuilding + +2006-05-30 Thomas Vander Stichele + + * gtk-doc.mak: + error out if gtkdoc-mktmpl finds unused declarations + +2006-05-28 Edward Hervey + + * gst.supp: + Reverting previous commit. That's good to know, Edward, but why ? + +2006-05-28 Edward Hervey + + * gst.supp: + Added suppresion for memleak in g_option_context_parse on fc5-64 + +2006-05-19 Thomas Vander Stichele + + * m4/gst-check.m4: + set GSTPB_PLUGINS_DIR just like GST_PLUGINS_DIR + +2006-05-18 Tim-Philipp Müller + + * check.mak: + Fix 'make help' in check directories, it should be + 'valgrind.gen-suppressions' not 'valgrind-gen-suppressions' + (not changing target to match help string on purpose to keep + scripts etc. functional). + +2006-05-18 Thomas Vander Stichele + + Patch by: Peter Kjellerstedt + + * m4/gst-arch.m4: + add support for CRIS and CRISv32. + +2006-05-17 Jan Schmidt + + * m4/gst-args.m4: + Fix the macros for command-line supplied package and origin names + so they don't end up being configure as "" (Fixes #341479) + +2006-05-14 Jan Schmidt + + * gtk-doc.mak: + Add uninstall rule to remove .devhelp2 files. + +2006-05-09 Edward Hervey + + * gst.supp: + Add suppression for GSlice version of + g_type_init calloc leak + +2006-04-05 Michael Smith + + * gst.supp: + Delete a bogus suppression for the registry code. + Generalise a suppression for a glib bug (see #337404) + +2006-04-04 Michael Smith + + * gst.supp: + Add a leak suppression: the existing glibc-doesn't-free-TLS one + wasn't triggering here. + +2006-04-04 Michael Smith + + * gst.supp: + Add some minimally-neccesary suppressions for my x86/dapper system. + +2006-04-01 Thomas Vander Stichele + + * plugins.xsl: + Do not display an origin link if origin does not start with http + See #323798 + +2006-04-01 Thomas Vander Stichele + + * m4/gst-args.m4: + * m4/gst-feature.m4: + add more macros + * m4/gst-x11.m4: + X11-related checks + +2006-04-01 Thomas Vander Stichele + + * m4/as-version.m4: + newer version + * m4/gst-args.m4: + * m4/gst-doc.m4: + update and add other macros to be shared across projects + +2006-03-24 Thomas Vander Stichele + + * gst.supp: + add a suppression for g_parse_debug_string + +2006-03-23 Stefan Kost + + * gstdoc-scangobj: + sync fully with gtkdoc-0.15 + +2006-03-23 Stefan Kost + + * gstdoc-scangobj: + * gtk-doc.mak: + sync a little with gtk-doc mainline + +2006-03-17 Wim Taymans + + * gst.supp: + add another clone suppression + change all glibc suppressions to match 2.3.* + +2006-03-09 Thomas Vander Stichele + + * m4/check.m4: + fix test so it actually works when the normal check is used + over debian's/ubuntu's + +2006-03-08 Jan Schmidt + + * check.mak: + Set G_SLICE=always-malloc when valgrinding tests + (closes #333272) + +2006-02-21 Jan Schmidt + + * m4/gst-glib2.m4: + Fix debug output when the GLib version prerequisite is not found + +2006-02-13 Andy Wingo + + * m4/check.m4: Hack around Debian/Ubuntu's broken installation of + the PIC version of check as libcheck_pic.a. Should work with + cross-compilation too. Grr. + +2006-02-06 Thomas Vander Stichele + + * m4/gst-default.m4: + switch to auto* sinks for defaults + +2006-02-02 Wim Taymans + + * check.mak: + add a .valgrind.gen-suppressions target to aid in generating + suppressions + * gst.supp: + add more repressions from my debian glibc as of today + +2006-02-02 Thomas Vander Stichele + + * gtk-doc-plugins.mak: + only add srcdir/gst if it exists + +2006-01-30 Thomas Vander Stichele + + * release.mak: + don't complain about disted enums in win32 + +2006-01-20 Thomas Vander Stichele + + * m4/gst-check.m4: + AC_SUBST CFLAGS and LIBS + do a non-command because something is stripping out our AC_SUBST + +2006-01-20 Thomas Vander Stichele + + * m4/gst-args.m4: + * m4/gst-valgrind.m4: + properly give a "no" result manually when providing a + not-found action to fix configure output + +2006-01-20 Thomas Vander Stichele + + * m4/pkg.m4: + update with a more recent version + +2006-01-07 Thomas Vander Stichele + + * gettext.patch: + make Makefile depend on LINGUAS, so rebuilds work when adding + a language + +2006-01-03 Michael Smith + + * check.mak: + Clarify error message from valgrind test runs. + +2005-12-16 Thomas Vander Stichele + + * m4/gst-arch.m4: + define HOST_CPU + +2005-11-29 Thomas Vander Stichele + + * check.mak: + add a valgrind-forever target for tests + +2005-11-28 Thomas Vander Stichele + + * check.mak: + when a "make test.check" run fails, make it rerun the test with + at least debug level 2 + +2005-11-14 Thomas Vander Stichele + + * m4/Makefile.am: + * m4/gst-check.m4: + fix check for base plugins + * m4/gst-default.m4: + add m4 to set default elements + +2005-10-18 Thomas Vander Stichele + + * m4/gst-check.m4: + check for tools correctly + +2005-10-18 Thomas Vander Stichele + + * gtk-doc.mak: + only enable breaking on new API when make distcheck passes, + not before + +2005-10-18 Thomas Vander Stichele + + * m4/gst-check.m4: + Resurrect Julien's dead body and wipe his mind clean + +2005-10-18 Thomas Vander Stichele + + * m4/gst-check.m4: + Kill Julien + +2005-10-17 Julien MOUTTE + + * m4/gst-check.m4: I know Thomas will kill me but this + ifelse statement seems incorrect as it is always setting + required to "yes". With this one it seems to work. Fixes + build of gst-plugins-base on my setup where gstreamer-check + is definitely not present/required. + +2005-10-18 Stefan Kost + + * gtk-doc.mak: + make build break on new api that has not been added to the + sections file + +2005-10-17 Thomas Vander Stichele + + * m4/gst-glib2.m4: + * m4/Makefile.am: + * m4/gst-check.m4: + add macro for easy checks for GStreamer libs + +2005-10-16 Thomas Vander Stichele + + * m4/gst-glib2.m4: + update, warn in error cases + +2005-10-16 Thomas Vander Stichele + + * m4/gst-error.m4: + add GST_SET_DEFAULT_LEVEL + +2005-10-16 Thomas Vander Stichele + + * m4/Makefile.am: + * m4/gst-gettext.m4: + remove the AM_GNU_GETTEXT* calls, they need to be in configure.ac + * m4/gst-glib2.m4: + clean up and re-use in core soon + * m4/gst-plugindir.m4: + macro to set up PLUGINDIR and plugindir define/var + +2005-10-15 Thomas Vander Stichele + + * m4/Makefile.am: + * m4/gst-gettext.m4: + add macro for setting up gettext + +2005-10-15 Thomas Vander Stichele + + * m4/gst-args.m4: + add some .m4's for argument checking that can be shared among modules + +2005-10-15 Thomas Vander Stichele + + * m4/as-libtool.m4: + set _LT_LDFLAGS + * m4/gst-libxml2.m4: + document + +2005-10-15 Thomas Vander Stichele + + * m4/gst-arch.m4: + indent a little + add AC_REQUIRE + * m4/gst-error.m4: + clean up + +2005-10-12 Thomas Vander Stichele + + * gst-autogen.sh: + update version detection expression to catch stuff like + Libtool (libtool15) 1.5.0 + +2005-10-11 Thomas Vander Stichele + + * gst.supp: + commit 6 new suppressions related to g_module_open; can these + really not be folded into one ? + +2005-10-11 Edward Hervey + + * gst.supp: + made the suppression more generic + Added pthread memleak suppresions + Added nss_parse_* memleak suppresion (used by g_option_context_parse) + +2005-10-11 Thomas Vander Stichele + + * check.mak: + be more strict, more leak resolution + * gst.supp: + clean up the g_type_init suppressions + +2005-10-07 Thomas Vander Stichele + + * m4/Makefile.am: + * m4/gst-valgrind.m4: + put the valgrind detection in an .m4 + +2005-09-29 Thomas Vander Stichele + + * check.mak: + add some more targets, like "help", but also more intensive tests + +2005-09-23 Thomas Vander Stichele + + * gtk-doc.mak: + make certain doc warnings fatal so people maintain docs again + +2005-09-23 Thomas Vander Stichele + + * Makefile.am: + * gtk-doc-plugins.mak: + * scangobj-merge.py: + merge additions from the .signals.new and .args.new file in + the original ones, only updating if necessary + +2005-09-23 Thomas Vander Stichele + + * gst-xmlinspect.py: + * gstdoc-scangobj: + * gtk-doc-plugins.mak: + fix properly for new API; make update in plugins dir now works + +2005-09-20 Thomas Vander Stichele + + * gst-xmlinspect.py: + * gstdoc-scangobj: + some fixes for new API + * gtk-doc-plugins.mak: + set environment properly + +2005-09-17 David Schleef + + * gtk-doc-plugins.mak: Use new environment variables. + +2005-09-16 Michael Smith + + * gstdoc-scangobj: + Make the scanobj code reflect registry/plugin API changes + +2005-09-15 Thomas Vander Stichele + + * gtk-doc-plugins.mak: + split out scanobj step (which will be run by doc maintainer) + from scan step (which will be run on every build) + clean up some of the commands for make distcheck + +2005-09-15 Thomas Vander Stichele + + * gtk-doc-plugins.mak: + * mangle-tmpl.py: + first stab at reorganizing the plugins build so we can maintain + element docs + +2005-09-14 David Schleef + + * as-libtool.mak: Remove + * m4/as-libtool.m4: The libtool bug that this worked around has + been fixed. + * m4/as-version.m4: Don't define GST_RELEASE, since it causes + config.h to be regenerated needlessly, and we don't use it. + +2005-09-14 Thomas Vander Stichele + + * gtk-doc-plugins.mak: + error out on inspect failure + +2005-09-14 Michael Smith + + * glib-gen.mak: + Don't call glib-mkenums with arguments that confuse/break MinGW, + fixes 316155. + +2005-09-03 Thomas Vander Stichele + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + * m4/gst-doc.m4: + separate out gtk-doc and docbook stuff + have two separate --enable configure flags + +2005-08-26 Thomas Vander Stichele + + * check.mak: + add a .gdb target; rebuild registry for each target, otherwise + a code rebuild always triggers a reg rebuild, and it's just too + annoying + * gstdoc-scangobj: + +2005-08-21 Thomas Vander Stichele + + * check.mak: + separate out REGISTRY_ENVIRONMENT; we want to use that from + our valgrind runs, but we also want TESTS_ENVIRONMENT to contain + everything that the first test, gst-register, needs + +2005-08-21 Thomas Vander Stichele + + * check.mak: + parse output of valgrind and check for definitely lost, and error + out; somehow I was led to believe valgrind returns non-zero for + leaks, but I can't make it do that, so let's parse + +2005-08-20 Thomas Vander Stichele + + * check.mak: + for some weird reason valgrind does not report actual memleaks + if GST_PLUGIN_PATH is set to anything but the core gstreamer dir + while valgrind is running. Since the registry is going to go + anyway, I don't want to waste any more time on this; I just run + valgrind without GST_PLUGIN_PATH set. Since the registry loading + doesn't check if GST_PLUGIN_PATH got changed as a reason to rebuild + the registry, that's actually fine. + +2005-08-15 Thomas Vander Stichele + + * mangle-tmpl.py: + keep original Long_Description; only insert an include if it's + not already the first line in there + * plugins.xsl: + output more information for plugins, including an origin hyperlink + +2005-08-15 Thomas Vander Stichele + + * gst-xmlinspect.py: + a first stab at inspecting plugins and outputting an xml description + * gtk-doc-plugins.mak: + a gtk-doc using snippet for plugins documentation + * plugins.xsl: + a stylesheet to convert gst-xmlinspect.py output to docbook output + for inclusion in the gtk-doc stuff + +2005-07-20 Ronald S. Bultje + + * m4/gst-doc.m4: + s/pdf/eps/ in test for whether we output EPS images (#309379). + +2005-07-18 Andy Wingo + + * m4/as-libtool-tags.m4: Ooh, backported from libtool 1.6. Much + better. Thanks, Paolo Bonzini! + + * m4/Makefile.am (EXTRA_DIST): + * m4/as-libtool-tags.m4: New file, tries to disable some CXX and + fortran checks. + +2005-07-08 Thomas Vander Stichele + + * m4/gst-error.m4: + add macro to set ERROR_CFLAGS + +2005-06-30 Jan Schmidt + + * gst-autogen.sh: + Remove the old autoregen.sh if it exists before recreating it, + to prevent confusing any shell process that might be reading it + currently. + +2005-06-29 Thomas Vander Stichele + + * m4/gtk-doc.m4: + added + +2005-06-03 Stefan Kost + + * gst-autogen.sh: create autoregen.sh *before* shifting the options + +2005-05-17 Thomas Vander Stichele + + * gst-autogen.sh: only update autoregen.sh on actual runs + +2005-03-11 Thomas Vander Stichele + + * m4/check.m4: m4 from the check unit test suite + +2004-12-14 David Schleef + + * m4/gst-arch.m4: remove MMX stuff, since it doesn't work and + isn't needed anywhere + +2004-12-08 Thomas Vander Stichele + + * gst-autogen.sh: + allow failure command to be run so we can clean upfrom autopoint + +2004-09-03 Zeeshan Ali Khattak + * m4/gst-feature.m4: Trying to correct the GST_CHECK_CONFIGPROG macro + +2004-07-21 Benjamin Otte + + * m4/.cvsignore: exciting updates for libtool m4 files + +2004-07-12 David Schleef + + * m4/as-objc.m4: Add a macro to test for objective C + +2004-06-12 Thomas Vander Stichele + + * m4/gst-feature.m4: + not all of them support --plugin-libs, so redirect stderr + +2004-06-12 Thomas Vander Stichele + + * m4/as-scrub-include.m4: + sync with upstream to 0.1.4. Fixes #132440 + +2004-06-07 Benjamin Otte + + * m4/gst-feature.m4: + write a big marker into configure output when checking next plugin + to allow easier parsing of why plugins are(n't) built. + +2004-06-01 Thomas Vander Stichele + + * m4/as-compiler-flag.m4: + * m4/as-compiler.m4: + * m4/as-libtool.m4: + * m4/as-version.m4: + sync with upstream, change sticky options to -ko + +2004-05-24 Thomas Vander Stichele + + * m4/as-scrub-include.m4: synced with upstream + +2004-05-03 Thomas Vander Stichele + + * po.mak: + snippet for updating .po files + +2004-03-18 Thomas Vander Stichele + + * Makefile.am: + * m4/Makefile.am: + integrate these with the dist + +2004-03-17 Thomas Vander Stichele + + * release.mak: add a release target + +2004-03-09 Thomas Vander Stichele + + patch by: Stephane Loeuillet + + * m4/ax_create_stdint_h.m4: + use head -n instead of head - (#136500) + +2004-03-05 Thomas Vander Stichele + + * m4/gst-doc.m4: don't build PS without dvips binary + +2004-02-22 Julio M. Merino Vidal + + reviewed by: Benjamin Otte + + * m4/as-docbook.m4: + don't use == operator with test(1) (fixes #135115) + +2004-02-16 Thomas Vander Stichele + + * common/m4/gst-arch.m4: x86_64 is x86 too (clue from Fedora 2 test) + +2004-02-13 Thomas Vander Stichele + + * m4/gst-feature.m4: + remove AM_CONDITIONAL for the subsystem since automake 1.6.x + requires that call be in configure.ac + +2004-02-13 Thomas Vander Stichele + + * m4/gst-libxml2.m4: + take required version as argument, and default to 2.4.9 if not + specified + +2004-02-12 Thomas Vander Stichele + + * m4/gst-feature.m4: + rename and fix up GST_CHECK_DISABLE_SUBSYSTEM + +2004-02-11 Thomas Vander Stichele + + * common/m4/as-ac-expand.m4: + * common/m4/as-auto-alt.m4: + * common/m4/as-compiler-flag.m4: + * common/m4/as-compiler.m4: + * common/m4/as-docbook.m4: + * common/m4/as-libtool.m4: + * common/m4/as-scrub-include.m4: + * common/m4/as-version.m4: + * common/m4/glib-gettext.m4: + * common/m4/gst-arch.m4: + * common/m4/gst-debuginfo.m4: + * common/m4/gst-doc.m4: + * common/m4/gst-feature.m4: + * common/m4/gst-function.m4: + * common/m4/gst-glib2.m4: + * common/m4/gst-gstreamer.m4: + * common/m4/gst-libxml2.m4: + * common/m4/gst-makecontext.m4: + * common/m4/gst-mcsc.m4: + * common/m4/pkg.m4: + fix underquoted macros as reported by automake 1.8.x (#133800) + +2004-02-11 Johan Dahlin + + * gst-autogen.sh: Use A-Z instead of A-z in sed expression to + avoid a warning + +2004-02-05 Thomas Vander Stichele + + * m4/gst-doc.m4: + we use --output-format=xml and --ingnore-files options to + gtkdoc-mkdb, which got added between 0.9 and 1.0 + +2004-02-04 Thomas Vander Stichele + + * m4/as-libtool.m4: remove AM_PROG_LIBTOOL so it can move back + to configure.ac to shut up libtoolize + +2004-02-03 Thomas Vander Stichele + + * glib-gen.mak: added; used to generate enums and marshal code + +2004-01-13 Thomas Vander Stichele + + * gettext.patch: added; used by autogen.sh to make sure + GETTEXT_PACKAGE is understood from po/Makefile.in.in -> po/Makefile.in + diff --git a/common/Makefile.am b/common/Makefile.am new file mode 100644 index 0000000..25966fc --- /dev/null +++ b/common/Makefile.am @@ -0,0 +1,22 @@ +SUBDIRS = m4 + +EXTRA_DIST = \ + ChangeLog \ + gettext.patch \ + glib-gen.mak gtk-doc.mak upload-doc.mak \ + cruft.mak release.mak win32.mak po.mak \ + parallel-subdirs.mak \ + gst-autogen.sh \ + check-exports \ + c-to-xml.py mangle-tmpl.py scangobj-merge.py \ + gtk-doc-plugins.mak \ + plugins.xsl gstdoc-scangobj \ + gst.supp check.mak \ + coverage/lcov.mak \ + coverage/coverage-report.pl \ + coverage/coverage-report.xsl \ + coverage/coverage-report-entry.pl \ + download-translations \ + extract-release-date-from-doap-file \ + gst-indent \ + orc.mak diff --git a/common/Makefile.in b/common/Makefile.in new file mode 100644 index 0000000..b4465d3 --- /dev/null +++ b/common/Makefile.in @@ -0,0 +1,756 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = common +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ChangeLog \ + README +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-docbook.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-default.m4 \ + $(top_srcdir)/common/m4/gst-doc.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAT_ENTRY_END = @CAT_ENTRY_END@ +CAT_ENTRY_START = @CAT_ENTRY_START@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@ +DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@ +DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@ +DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@ +DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ = @GLIB_REQ@ +GREP = @GREP@ +GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@ +GSTPD_PLUGINS_DIR = @GSTPD_PLUGINS_DIR@ +GSTPG_PLUGINS_DIR = @GSTPG_PLUGINS_DIR@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_BASE_CFLAGS = @GST_BASE_CFLAGS@ +GST_BASE_LIBS = @GST_BASE_LIBS@ +GST_CFLAGS = @GST_CFLAGS@ +GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@ +GST_CHECK_LIBS = @GST_CHECK_LIBS@ +GST_CURRENT = @GST_CURRENT@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBS = @GST_LIBS@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGINS_BAD_CFLAGS = @GST_PLUGINS_BAD_CFLAGS@ +GST_PLUGINS_BAD_DIR = @GST_PLUGINS_BAD_DIR@ +GST_PLUGINS_BAD_LIBS = @GST_PLUGINS_BAD_LIBS@ +GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@ +GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@ +GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@ +GST_PLUGINS_DIR = @GST_PLUGINS_DIR@ +GST_PLUGINS_GOOD_CFLAGS = @GST_PLUGINS_GOOD_CFLAGS@ +GST_PLUGINS_GOOD_DIR = @GST_PLUGINS_GOOD_DIR@ +GST_PLUGINS_GOOD_LIBS = @GST_PLUGINS_GOOD_LIBS@ +GST_REVISION = @GST_REVISION@ +GST_TOOLS_DIR = @GST_TOOLS_DIR@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ +HAVE_DVIPS = @HAVE_DVIPS@ +HAVE_EPSTOPDF = @HAVE_EPSTOPDF@ +HAVE_JADETEX = @HAVE_JADETEX@ +HAVE_PNGTOPNM = @HAVE_PNGTOPNM@ +HAVE_PNMTOPS = @HAVE_PNMTOPS@ +HAVE_PS2PDF = @HAVE_PS2PDF@ +HAVE_XMLLINT = @HAVE_XMLLINT@ +HAVE_XSLTPROC = @HAVE_XSLTPROC@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCGROUP_CFLAGS = @LIBCGROUP_CFLAGS@ +LIBCGROUP_LIBS = @LIBCGROUP_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +XML_CATALOG = @XML_CATALOG@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = m4 +EXTRA_DIST = \ + ChangeLog \ + gettext.patch \ + glib-gen.mak gtk-doc.mak upload-doc.mak \ + cruft.mak release.mak win32.mak po.mak \ + parallel-subdirs.mak \ + gst-autogen.sh \ + check-exports \ + c-to-xml.py mangle-tmpl.py scangobj-merge.py \ + gtk-doc-plugins.mak \ + plugins.xsl gstdoc-scangobj \ + gst.supp check.mak \ + coverage/lcov.mak \ + coverage/coverage-report.pl \ + coverage/coverage-report.xsl \ + coverage/coverage-report-entry.pl \ + download-translations \ + extract-release-date-from-doap-file \ + gst-indent \ + orc.mak + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu common/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu common/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/common/README b/common/README new file mode 100644 index 0000000..83a1b88 --- /dev/null +++ b/common/README @@ -0,0 +1,255 @@ +GStreamer @SERIES_VERSION@ + +WHAT IT IS +---------- + +This is GStreamer, a framework for streaming media. + +WHERE TO START +-------------- + +We have a website at +http://gstreamer.freedesktop.org/ + +You should start by going through our FAQ at +http://gstreamer.freedesktop.org/data/doc/gstreamer/head/faq/html/ + +There is more documentation; go to +http://gstreamer.freedesktop.org/documentation + +You can subscribe to our mailing lists; see the website for details. + +We track bugs in GNOME's bugzilla; see the website for details. + +You can join us on IRC - #gstreamer on irc.freenode.org + +GStreamer 1.0 series +-------------------- + +Starring + + GSTREAMER + +The core around which all other modules revolve. Base functionality and +libraries, some essential elements, documentation, and testing. + + BASE + +A well-groomed and well-maintained collection of GStreamer plug-ins and +elements, spanning the range of possible types of elements one would want +to write for GStreamer. + +And introducing, for the first time ever, on the development screen ... + + THE GOOD + + --- "Such ingratitude. After all the times I've saved your life." + +A collection of plug-ins you'd want to have right next to you on the +battlefield. Shooting sharp and making no mistakes, these plug-ins have it +all: good looks, good code, and good licensing. Documented and dressed up +in tests. If you're looking for a role model to base your own plug-in on, +here it is. + +If you find a plot hole or a badly lip-synced line of code in them, +let us know - it is a matter of honour for us to ensure Blondie doesn't look +like he's been walking 100 miles through the desert without water. + + THE UGLY + + --- "When you have to shoot, shoot. Don't talk." + +There are times when the world needs a color between black and white. +Quality code to match the good's, but two-timing, backstabbing and ready to +sell your freedom down the river. These plug-ins might have a patent noose +around their neck, or a lock-up license, or any other problem that makes you +think twice about shipping them. + +We don't call them ugly because we like them less. Does a mother love her +son less because he's not as pretty as the other ones ? No - she commends +him on his great personality. These plug-ins are the life of the party. +And we'll still step in and set them straight if you report any unacceptable +behaviour - because there are two kinds of people in the world, my friend: +those with a rope around their neck and the people who do the cutting. + + THE BAD + + --- "That an accusation?" + +No perfectly groomed moustache or any amount of fine clothing is going to +cover up the truth - these plug-ins are Bad with a capital B. +They look fine on the outside, and might even appear to get the job done, but +at the end of the day they're a black sheep. Without a golden-haired angel +to watch over them, they'll probably land in an unmarked grave at the final +showdown. + +Don't bug us about their quality - exercise your Free Software rights, +patch up the offender and send us the patch on the fastest steed you can +steal from the Confederates. Because you see, in this world, there's two +kinds of people, my friend: those with loaded guns and those who dig. +You dig. + +The Lowdown +----------- + + --- "I've never seen so many plug-ins wasted so badly." + +GStreamer Plug-ins has grown so big that it's hard to separate the wheat from +the chaff. Also, distributors have brought up issues about the legal status +of some of the plug-ins we ship. To remedy this, we've divided the previous +set of available plug-ins into four modules: + +- gst-plugins-base: a small and fixed set of plug-ins, covering a wide range + of possible types of elements; these are continuously kept up-to-date + with any core changes during the development series. + + - We believe distributors can safely ship these plug-ins. + - People writing elements should base their code on these elements. + - These elements come with examples, documentation, and regression tests. + +- gst-plugins-good: a set of plug-ins that we consider to have good quality + code, correct functionality, our preferred license (LGPL for the plug-in + code, LGPL or LGPL-compatible for the supporting library). + + - We believe distributors can safely ship these plug-ins. + - People writing elements should base their code on these elements. + +- gst-plugins-ugly: a set of plug-ins that have good quality and correct + functionality, but distributing them might pose problems. The license + on either the plug-ins or the supporting libraries might not be how we'd + like. The code might be widely known to present patent problems. + + - Distributors should check if they want/can ship these plug-ins. + - People writing elements should base their code on these elements. + +- gst-plugins-bad: a set of plug-ins that aren't up to par compared to the + rest. They might be close to being good quality, but they're missing + something - be it a good code review, some documentation, a set of tests, + a real live maintainer, or some actual wide use. + If the blanks are filled in they might be upgraded to become part of + either gst-plugins-good or gst-plugins-ugly, depending on the other factors. + + - If the plug-ins break, you can't complain - instead, you can fix the + problem and send us a patch, or bribe someone into fixing them for you. + - New contributors can start here for things to work on. + +PLATFORMS +--------- + +- Linux is of course fully supported +- FreeBSD is reported to work; other BSDs should work too +- Solaris is reported to work; a specific sunaudiosink plugin has been written +- MacOSX works, binary 1.x packages can be built using the cerbero build tool +- Windows works; binary 1.x packages can be built using the cerbero build tool + - MSys/MinGW builds + - Microsoft Visual Studio builds are not yet available or supported +- Android works, binary 1.x packages can be built using the cerbero build tool +- iOS works + +INSTALLING FROM PACKAGES +------------------------ + +You should always prefer installing from packages first. GStreamer is +well-maintained for a number of distributions, including Fedora, Debian, +Ubuntu, Mandrake, Gentoo, ... + +Only in cases where you: +- want to hack on GStreamer +- want to verify that a bug has been fixed +- do not have a sane distribution +should you choose to build from source tarballs or git. + +Find more information about the various packages at +http://gstreamer.freedesktop.org/download/ + +COMPILING FROM SOURCE TARBALLS +------------------------------ + +- again, make sure that you really need to install from source ! + If GStreamer is one of your first projects ever that you build from source, + consider taking on an easier project. + +- check output of ./configure --help to see if any options apply to you +- run + ./configure + make + + to build GStreamer. +- if you want to install it (not required, but what you usually want to do), run + make install + +- try out a simple test: + gst-launch -v fakesrc num_buffers=5 ! fakesink + (If you didn't install GStreamer, prefix gst-launch with tools/) + + If it outputs a bunch of messages from fakesrc and fakesink, everything is + ok. + + If it did not work, keep in mind that you might need to adjust the + PATH and/or LD_LIBRARY_PATH environment variables to make the system + find GStreamer in the prefix where you installed (by default that is /usr/local). + +- After this, you're ready to install gst-plugins, which will provide the + functionality you're probably looking for by now, so go on and read + that README. + +COMPILING FROM GIT +------------------ + +When building from git sources, you will need to run autogen.sh to generate +the build system files. + +You will need a set of additional tools typical for building from git, +including: +- autoconf +- automake +- libtool + +autogen.sh will check for recent enough versions and complain if you don't have +them. You can also specify specific versions of automake and autoconf with +--with-automake and --with-autoconf + +Check autogen.sh options by running autogen.sh --help + +autogen.sh can pass on arguments to configure + +When you have done this once, you can use autoregen.sh to re-autogen with +the last passed options as a handy shortcut. Use it. + +After the autogen.sh stage, you can follow the directions listed in +"COMPILING FROM SOURCE" + +You can also run your whole git stack uninstalled in your home directory, +so that you can quickly test changes without affecting your system setup or +interfering with GStreamer installed from packages. Many GStreamer developers +use an uninstalled setup for their work. + +There is a 'create-uninstalled-setup.sh' script in + + http://cgit.freedesktop.org/gstreamer/gstreamer/tree/scripts/ + +to easily create an uninstalled setup from scratch. + + +PLUG-IN DEPENDENCIES AND LICENSES +--------------------------------- + +GStreamer is developed under the terms of the LGPL (see LICENSE file for +details). Some of our plug-ins however rely on libraries which are available +under other licenses. This means that if you are distributing an application +which has a non-GPL compatible license (for instance a closed-source +application) with GStreamer, you have to make sure not to distribute GPL-linked +plug-ins. + +When using GPL-linked plug-ins, GStreamer is for all practical reasons +under the GPL itself. + +HISTORY +------- + +The fundamental design comes from the video pipeline at Oregon Graduate +Institute, as well as some ideas from DirectMedia. It's based on plug-ins that +will provide the various codec and other functionality. The interface +hopefully is generic enough for various companies (ahem, Apple) to release +binary codecs for Linux, until such time as they get a clue and release the +source. diff --git a/common/c-to-xml.py b/common/c-to-xml.py new file mode 100644 index 0000000..7a7a35b --- /dev/null +++ b/common/c-to-xml.py @@ -0,0 +1,36 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +""" +Convert a C program to valid XML to be included in docbook +""" + +from __future__ import print_function, unicode_literals + +import sys +import os +from xml.sax import saxutils + +def main(): + if len(sys.argv) == 1: + sys.stderr.write("Please specify a source file to convert") + sys.exit(1) + source = sys.argv[1] + + if not os.path.exists(source): + sys.stderr.write("%s does not exist.\n" % source) + sys.exit(1) + + content = open(source, "r").read() + + # print header + print ('') + print ('') + print () + print ('') + + # print content + print (saxutils.escape(content)) + print ('') + +main() diff --git a/common/check-exports b/common/check-exports new file mode 100755 index 0000000..ee01ff7 --- /dev/null +++ b/common/check-exports @@ -0,0 +1,54 @@ +#!/bin/sh +# check-exports +# +# quick'n'dirty script that retrieves the list of exported symbols of a given +# library using 'nm', and compares that against the list of symbols-to-export +# of our win32/common/libfoo.def files. + +if [ $# -ne 2 ]; then + echo "Usage: $0 library.def library.so" + exit 1 +fi + +def_path="$1" +def_name="$(basename $def_path)" +lib_path="$2" + +lib_result="`mktemp /tmp/defname.XXXXXX`" + +LC_ALL=C +export LC_ALL + +# On Solaris, add -p to get the correct output format +NMARGS= +if nm -V 2>&1 |grep Solaris > /dev/null; then + NMARGS=-p +fi + +# _end is special cased because for some reason it is reported as an exported +# BSS symbol, unlike on linux where it's a local absolute symbol. +nm $NMARGS $lib_path | awk \ + '{ + if ($3 ~ /^[_]?(gst_|Gst|GST_).*/) + { + if ($2 ~ /^[BSDG]$/) + print "\t" $3 " DATA" + else if ($2 == "T") + print "\t" $3 + } + }' | sort | awk '{ if (NR == 1) print "EXPORTS"; print $0; }' \ + > $lib_result + +diffoutput=`diff -u $def_path $lib_result` +diffresult=$? + +rm $lib_result + +if test "$diffresult" -eq 0; then + exit 0; +else + echo -n "$diffoutput" >&2 + echo >&2 + exit 1; +fi + diff --git a/common/check.mak b/common/check.mak new file mode 100644 index 0000000..611546a --- /dev/null +++ b/common/check.mak @@ -0,0 +1,252 @@ +# keep target around, since it's referenced in the modules' Makefiles +clean-local-check: + @echo + +if HAVE_VALGRIND +# hangs spectacularly on some machines, so let's not do this by default yet +check-valgrind: + $(MAKE) valgrind +else +check-valgrind: + @true +endif + +LOOPS ?= 10 + +# run any given test by running make test.check +# if the test fails, run it again at at least debug level 2 +%.check: % + @$(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=20 \ + $* || \ + $(TESTS_ENVIRONMENT) \ + GST_DEBUG=$$GST_DEBUG,*:2 \ + CK_DEFAULT_TIMEOUT=20 \ + $* + +# just like 'check', but don't run it again if it fails (useful for debugging) +%.check-norepeat: % + @$(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=20 \ + $* + +# run any given test in a loop +%.torture: % + @for i in `seq 1 $(LOOPS)`; do \ + $(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=20 \ + $*; done + +# run any given test in an infinite loop +%.forever: % + @while true; do \ + $(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=20 \ + $* || break; done + +# valgrind any given test by running make test.valgrind +%.valgrind: % + @$(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=360 \ + G_SLICE=always-malloc \ + $(LIBTOOL) --mode=execute \ + $(VALGRIND_PATH) -q \ + $(foreach s,$(SUPPRESSIONS),--suppressions=$(s)) \ + --tool=memcheck --leak-check=full --trace-children=yes \ + --show-possibly-lost=no \ + --leak-resolution=high --num-callers=20 \ + ./$* 2>&1 | tee valgrind.log + @if grep "==" valgrind.log > /dev/null 2>&1; then \ + rm valgrind.log; \ + exit 1; \ + fi + @rm valgrind.log + +# valgrind any given test and generate suppressions for it +%.valgrind.gen-suppressions: % + @$(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=360 \ + G_SLICE=always-malloc \ + $(LIBTOOL) --mode=execute \ + $(VALGRIND_PATH) -q \ + $(foreach s,$(SUPPRESSIONS),--suppressions=$(s)) \ + --tool=memcheck --leak-check=full --trace-children=yes \ + --show-possibly-lost=no \ + --leak-resolution=high --num-callers=20 \ + --gen-suppressions=all \ + ./$* 2>&1 | tee suppressions.log + +# valgrind torture any given test +%.valgrind-torture: % + @for i in `seq 1 $(LOOPS)`; do \ + $(MAKE) $*.valgrind || \ + (echo "Failure after $$i runs"; exit 1) || \ + exit 1; \ + done + @banner="All $(LOOPS) loops passed"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo $$dashes; echo $$banner; echo $$dashes + +# valgrind any given test until failure by running make test.valgrind-forever +%.valgrind-forever: % + @while $(MAKE) $*.valgrind; do \ + true; done + +# gdb any given test by running make test.gdb +%.gdb: % + @$(TESTS_ENVIRONMENT) \ + CK_FORK=no \ + $(LIBTOOL) --mode=execute \ + gdb $* + +%.lcov-reset: + $(MAKE) $*.lcov-run + $(MAKE) $*.lcov-report + +%.lcov: % + $(MAKE) $*.lcov-reset + +if GST_GCOV_ENABLED +%.lcov-clean: + $(MAKE) -C $(top_builddir) lcov-clean + +%.lcov-run: + $(MAKE) $*.lcov-clean + $(MAKE) $*.check + +%.lcov-report: + $(MAKE) -C $(top_builddir) lcov-report +else +%.lcov-run: + echo "Need to reconfigure with --enable-gcov" + +%.lcov-report: + echo "Need to reconfigure with --enable-gcov" +endif + +# torture tests +torture: $(TESTS) + -rm test-registry.* + @echo "Torturing tests ..." + @for i in `seq 1 $(LOOPS)`; do \ + $(MAKE) check || \ + (echo "Failure after $$i runs"; exit 1) || \ + exit 1; \ + done + @banner="All $(LOOPS) loops passed"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo $$dashes; echo $$banner; echo $$dashes + +# forever tests +forever: $(TESTS) + -rm test-registry.* + @echo "Forever tests ..." + @while true; do \ + $(MAKE) check || \ + (echo "Failure"; exit 1) || \ + exit 1; \ + done + +# valgrind all tests +valgrind: $(TESTS) + @echo "Valgrinding tests ..." + @failed=0; \ + for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(TESTS)); do \ + $(MAKE) $$t.valgrind; \ + if test "$$?" -ne 0; then \ + echo "Valgrind error for test $$t"; \ + failed=`expr $$failed + 1`; \ + whicht="$$whicht $$t"; \ + fi; \ + done; \ + if test "$$failed" -ne 0; then \ + echo "$$failed tests had leaks or errors under valgrind:"; \ + echo "$$whicht"; \ + false; \ + fi + +# valgrind all tests until failure +valgrind-forever: $(TESTS) + -rm test-registry.* + @echo "Forever valgrinding tests ..." + @while true; do \ + $(MAKE) valgrind || \ + (echo "Failure"; exit 1) || \ + exit 1; \ + done + +# valgrind torture all tests +valgrind-torture: $(TESTS) + -rm test-registry.* + @echo "Torturing and valgrinding tests ..." + @for i in `seq 1 $(LOOPS)`; do \ + $(MAKE) valgrind || \ + (echo "Failure after $$i runs"; exit 1) || \ + exit 1; \ + done + @banner="All $(LOOPS) loops passed"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo $$dashes; echo $$banner; echo $$dashes + +# valgrind all tests and generate suppressions +valgrind.gen-suppressions: $(TESTS) + @echo "Valgrinding tests ..." + @failed=0; \ + for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(TESTS)); do \ + $(MAKE) $$t.valgrind.gen-suppressions; \ + if test "$$?" -ne 0; then \ + echo "Valgrind error for test $$t"; \ + failed=`expr $$failed + 1`; \ + whicht="$$whicht $$t"; \ + fi; \ + done; \ + if test "$$failed" -ne 0; then \ + echo "$$failed tests had leaks or errors under valgrind:"; \ + echo "$$whicht"; \ + false; \ + fi + +# inspect every plugin feature +GST_INSPECT = $(GST_TOOLS_DIR)/gst-inspect-$(GST_API_VERSION) +inspect: + @echo "Inspecting features ..." + @for e in `$(TESTS_ENVIRONMENT) $(GST_INSPECT) | head -n -2 \ + | cut -d: -f2`; \ + do echo Inspecting $$e; \ + $(GST_INSPECT) $$e > /dev/null 2>&1; done + +help: + @echo + @echo "make check -- run all checks" + @echo "make torture -- run all checks $(LOOPS) times" + @echo "make (dir)/(test).check -- run the given check once, repeat with GST_DEBUG=*:2 if it fails" + @echo "make (dir)/(test).check-norepeat -- run the given check once, but don't run it again if it fails" + @echo "make (dir)/(test).forever -- run the given check forever" + @echo "make (dir)/(test).torture -- run the given check $(LOOPS) times" + @echo + @echo "make (dir)/(test).gdb -- start up gdb for the given test" + @echo + @echo "make valgrind -- valgrind all tests" + @echo "make valgrind-forever -- valgrind all tests forever" + @echo "make valgrind-torture -- valgrind all tests $(LOOPS) times" + @echo "make valgrind.gen-suppressions -- generate suppressions for all tests" + @echo " and save to suppressions.log" + @echo "make (dir)/(test).valgrind -- valgrind the given test" + @echo "make (dir)/(test).valgrind-forever -- valgrind the given test forever" + @echo "make (dir)/(test).valgrind-torture -- valgrind the given test $(LOOPS) times" + @echo "make (dir)/(test).valgrind.gen-suppressions -- generate suppressions" + @echo " and save to suppressions.log" + @echo "make inspect -- inspect all plugin features" + @echo + @echo + @echo "Additionally, you can use the GST_CHECKS environment variable to" + @echo "specify which test(s) should be run. This is useful if you are" + @echo "debugging a failure in one particular test, or want to reproduce" + @echo "a race condition in a single test." + @echo + @echo "Examples:" + @echo + @echo " GST_CHECKS=test_this,test_that make element/foobar.check" + @echo " GST_CHECKS=test_many_threads make element/foobar.forever" + @echo + diff --git a/common/coverage/coverage-report-entry.pl b/common/coverage/coverage-report-entry.pl new file mode 100644 index 0000000..d0036b3 --- /dev/null +++ b/common/coverage/coverage-report-entry.pl @@ -0,0 +1,69 @@ +#!/usr/bin/perl +# +# Copyright (C) 2006 Daniel Berrange +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +print < + +Coverage report for $ARGV[0] + + + +

Coverage report for $ARGV[0]

+ +
+EOF
+
+
+while (<>) {
+    s/&/&/g;
+    s//>/g;
+
+    if (/^\s*function (\S+) called (\d+) returned \d+% blocks executed \d+%/) {
+	my $class = $2 > 0 ? "perfect" : "terrible";
+	$_ = "$_";
+    } elsif (/^\s*branch\s+\d+\s+taken\s+(\d+)%\s+.*$/) {
+	my $class = $1 > 0 ? "perfect" : "terrible";
+	$_ = "$_";
+    } elsif (/^\s*branch\s+\d+\s+never executed.*$/) {
+	my $class = "terrible";
+	$_ = "$_";
+    } elsif (/^\s*call\s+\d+\s+never executed.*$/) {
+	my $class = "terrible";
+	$_ = "$_";
+    } elsif (/^\s*call\s+\d+\s+returned\s+(\d+)%.*$/) {
+	my $class = $1 > 0 ? "perfect" : "terrible";
+	$_ = "$_";
+    }
+
+    print;
+}
+
+print <
+
+
+EOF
diff --git a/common/coverage/coverage-report.pl b/common/coverage/coverage-report.pl
new file mode 100644
index 0000000..18bd6f1
--- /dev/null
+++ b/common/coverage/coverage-report.pl
@@ -0,0 +1,125 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2006 Daniel Berrange
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+use warnings;
+use strict;
+
+my %coverage = ( functions => {}, files => {} );
+
+my %filemap;
+
+my $type;
+my $name;
+
+my @functions;
+
+while (<>) {
+    if (/^Function '(.*)'\s*$/) {
+	$type = "function";
+	$name = $1;
+	$coverage{$type}->{$name} = {};
+	push @functions, $name;
+    } elsif (/^File '(.*?)'\s*$/) {
+	$type = "file";
+	$name = $1;
+	$coverage{$type}->{$name} = {};
+
+	foreach my $func (@functions) {
+	    $coverage{"function"}->{$func}->{file} = $name;
+	}
+	@functions = ();
+    } elsif (/^Lines executed:(.*)%\s*of\s*(\d+)\s*$/) {
+	$coverage{$type}->{$name}->{lines} = $2;
+	$coverage{$type}->{$name}->{linesCoverage} = $1;
+    } elsif (/^Branches executed:(.*)%\s*of\s*(\d+)\s*$/) {
+	$coverage{$type}->{$name}->{branches} = $2;
+	$coverage{$type}->{$name}->{branchesCoverage} = $1;
+    } elsif (/^Taken at least once:(.*)%\s*of\s*(\d+)\s*$/) {
+	$coverage{$type}->{$name}->{conds} = $2;
+	$coverage{$type}->{$name}->{condsCoverage} = $1;
+    } elsif (/^Calls executed:(.*)%\s*of\s*(\d+)\s*$/) {
+	$coverage{$type}->{$name}->{calls} = $2;
+	$coverage{$type}->{$name}->{callsCoverage} = $1;
+    } elsif (/^No branches$/) {
+	$coverage{$type}->{$name}->{branches} = 0;
+	$coverage{$type}->{$name}->{branchesCoverage} = "100.00";
+	$coverage{$type}->{$name}->{conds} = 0;
+	$coverage{$type}->{$name}->{condsCoverage} = "100.00";
+    } elsif (/^No calls$/) {
+	$coverage{$type}->{$name}->{calls} = 0;
+	$coverage{$type}->{$name}->{callsCoverage} = "100.00";
+    } elsif (/^\s*(.*):creating '(.*)'\s*$/) {
+	$filemap{$1} = $2;
+    } elsif (/^\s*$/) {
+	# nada
+    } else {
+	warn "Shit [$_]\n";
+    }
+}
+
+my %summary;
+foreach my $type ("function", "file") {
+    $summary{$type} = {};
+    foreach my $m ("lines", "branches", "conds", "calls") {
+	my $totalGot = 0;
+	my $totalMiss = 0;
+	my $count = 0;
+	foreach my $func (keys %{$coverage{function}}) {
+	    $count++;
+	    my $got = $coverage{function}->{$func}->{$m};
+	    $totalGot += $got;
+	    my $miss = $got * $coverage{function}->{$func}->{$m ."Coverage"} / 100;
+	    $totalMiss += $miss;
+	}
+	$summary{$type}->{$m} = sprintf("%d", $totalGot);
+	$summary{$type}->{$m . "Coverage"} = sprintf("%.2f", $totalMiss / $totalGot * 100);
+    }
+}
+
+
+
+print "\n";
+
+foreach my $type ("function", "file") {
+    printf "<%ss>\n", $type;
+    foreach my $name (sort { $a cmp $b } keys %{$coverage{$type}}) {
+	my $rec = $coverage{$type}->{$name};
+	printf "  \n", $name, ($type eq "file" ? $filemap{$name} : $filemap{$rec->{file}});
+	printf "    \n", $rec->{lines}, $rec->{linesCoverage};
+	if (exists $rec->{branches}) {
+	    printf "    \n", $rec->{branches}, $rec->{branchesCoverage};
+	}
+	if (exists $rec->{conds}) {
+	    printf "    \n", $rec->{conds}, $rec->{condsCoverage};
+	}
+	if (exists $rec->{calls}) {
+	    printf "    \n", $rec->{calls}, $rec->{callsCoverage};
+	}
+	print  "  \n";
+    }
+
+    printf "  \n";
+    printf "    \n", $summary{$type}->{lines}, $summary{$type}->{linesCoverage};
+    printf "    \n", $summary{$type}->{branches}, $summary{$type}->{branchesCoverage};
+    printf "    \n", $summary{$type}->{conds}, $summary{$type}->{condsCoverage};
+    printf "    \n", $summary{$type}->{calls}, $summary{$type}->{callsCoverage};
+    printf  "  \n";
+    printf "\n", $type;
+}
+
+print "\n";
diff --git a/common/coverage/coverage-report.xsl b/common/coverage/coverage-report.xsl
new file mode 100644
index 0000000..3fe124b
--- /dev/null
+++ b/common/coverage/coverage-report.xsl
@@ -0,0 +1,235 @@
+
+
+
+
+  
+
+  
+    
+      
+        Coverage report
+        
+      
+      
+        

Coverage report

+ + + +
+ + +

Function coverage

+ + + +
+ + + +

File coverage

+ + + +
+ + + + + + + + + + + + + + + + + + + + + odd + + + even + + + + + + + + + + + + + + odd + + + even + + + + + + +
NameLinesBranchesConditionsCalls
+
+ + + + + + + + + + + + + + Summary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + perfect + + + excellant + + + good + + + poor + + + bad + + + terrible + + + + + % of + + +
diff --git a/common/coverage/lcov.mak b/common/coverage/lcov.mak new file mode 100644 index 0000000..b45728a --- /dev/null +++ b/common/coverage/lcov.mak @@ -0,0 +1,47 @@ +## .PHONY so it always rebuilds it +.PHONY: lcov-reset lcov lcov-run lcov-report lcov-upload lcov-clean + +# run lcov from scratch, always +lcov-reset: + $(MAKE) lcov-run + $(MAKE) lcov-report + +# run lcov from scratch if the dir is not there +lcov: + $(MAKE) lcov-reset + +if GST_GCOV_ENABLED +# reset lcov stats +lcov-clean: + @-rm -rf lcov + lcov --directory . --zerocounters + +# reset run coverage tests +lcov-run: + -$(MAKE) lcov-clean + -if test -d tests/check; then $(MAKE) -C tests/check inspect; fi + -$(MAKE) check + +# generate report based on current coverage data +lcov-report: + mkdir lcov + lcov --compat-libtool --directory . --capture --output-file lcov/lcov.info + lcov --list-full-path -l lcov/lcov.info | grep -v "`cd $(top_srcdir) && pwd`" | cut -d\| -f1 > lcov/remove + lcov --list-full-path -l lcov/lcov.info | grep "tests/check/" | cut -d\| -f1 >> lcov/remove + lcov --list-full-path -l lcov/lcov.info | grep "docs/plugins/" | cut -d\| -f1 >> lcov/remove + lcov -r lcov/lcov.info `cat lcov/remove` > lcov/lcov.cleaned.info + rm lcov/remove + mv lcov/lcov.cleaned.info lcov/lcov.info + genhtml -t "$(PACKAGE_STRING)" -o lcov --num-spaces 2 lcov/lcov.info + +lcov-upload: lcov + rsync -rvz -e ssh --delete lcov/* gstreamer.freedesktop.org:/srv/gstreamer.freedesktop.org/www/data/coverage/lcov/$(PACKAGE) + +else +lcov-run: + echo "Need to reconfigure with --enable-gcov" + +lcov-report: + echo "Need to reconfigure with --enable-gcov" +endif + diff --git a/common/cruft.mak b/common/cruft.mak new file mode 100644 index 0000000..53eec24 --- /dev/null +++ b/common/cruft.mak @@ -0,0 +1,56 @@ +# checks for left-over files in the (usually uninstalled) tree, ie. for +# stuff that best be deleted to avoid problems like having old plugin binaries +# lying around. +# +# set CRUFT_FILES and/or CRUFT_DIRS in your Makefile.am when you include this + +check-cruft: + @cruft_files=""; cruft_dirs=""; \ + for f in $(CRUFT_FILES); do \ + if test -e $$f; then \ + cruft_files="$$cruft_files $$f"; \ + fi \ + done; \ + for d in $(CRUFT_DIRS); do \ + if test -e $$d; then \ + cruft_dirs="$$cruft_dirs $$d"; \ + fi \ + done; \ + if test "x$$cruft_files$$cruft_dirs" != x; then \ + echo; \ + echo "**** CRUFT ALERT *****"; \ + echo; \ + echo "The following files and directories may not be needed any "; \ + echo "longer (usually because a plugin has been merged into "; \ + echo "another plugin, moved to a different module, or been "; \ + echo "renamed), and you probably want to clean them up if you "; \ + echo "don't have local changes: "; \ + echo; \ + for f in $$cruft_files; do echo "file $$f"; done; \ + echo; \ + for d in $$cruft_dirs; do echo "directory $$d"; done; \ + echo; \ + echo "'make clean-cruft' will remove these for you."; \ + echo; \ + fi + +clean-cruft-dirs: + @for d in $(CRUFT_DIRS); do \ + if test -e $$d; then \ + rm -r "$$d" && echo "Removed directory $$d"; \ + fi \ + done + +clean-cruft-files: + @for f in $(CRUFT_FILES); do \ + if test -e $$f; then \ + rm "$$f" && echo "Removed file $$f"; \ + fi \ + done + +clean-cruft: clean-cruft-dirs clean-cruft-files + +# also might want to add this to your Makefile.am: +# +# all-local: check-cruft + diff --git a/common/download-translations b/common/download-translations new file mode 100755 index 0000000..aef1d31 --- /dev/null +++ b/common/download-translations @@ -0,0 +1,152 @@ +#!/bin/sh +# Shell script to download the latest translations for a given GStreamer +# package from translationproject.org + + +# DOMAINS based on http://translationproject.org/extra/matrix.html +# We need to check all domains, not only po/LINGUAS, since there might be +# new translations +DOMAINS=\ +"af am ar az be bg pt_BR bs ca zh_CN cs cy da de el eo es et eu fa fi fr "\ +"ga en_GB gl gu he hi zh_HK hr hu id is it ja ko ku ky lg lt lv mk mn ms "\ +"mt nb ne nl nn or pa pl pt rm ro ru rw sk sl sq sr sv ta tq th tk "\ +"tr zh_TW uk ven vi wa xh zu" + +# for testing/debugging: +#DOMAINS="es fr hu sv pl xx" + +# check for 'diff' program +diff --version 2>/dev/null >/dev/null +if [ ! $? ]; then + echo "==== You must have the 'diff' program installed for this script ====" + exit 1 +fi + +# check for 'wget' program +wget --version 2>/dev/null >/dev/null +if [ ! $? ]; then + echo "==== You must have the 'wget' program installed for this script ====" + exit 1 +fi + +# make sure we're in the top-level directory +if [ ! -d ./po ]; then + echo "==== No ./po directory in the current working directory ====" + exit 1 +fi + +# make sure a package argument was passed to us +if [ -z "$1" ]; then + echo "Usage: $0 PACKAGE, e.g. $0 gst-plugins-good" + exit 1 +fi + +if test "$1" != "gstreamer" -a \ + "$1" != "gst-plugins-base" -a \ + "$1" != "gst-plugins-good" -a \ + "$1" != "gst-plugins-ugly" -a \ + "$1" != "gst-plugins-bad"; then + echo "Unexpected package '$1' ?!" + exit 1 +fi + +PACKAGE="$1" + +DOMAINS_TO_ADD="" +DOMAINS_UPDATED="" +DOMAINS_NOT_IN_LINGUAS="" + +echo "Downloading latest translation files for package $PACKAGE ..." +echo + +for d in $DOMAINS +do + PACKAGE_PO_URL_BASE="http://translationproject.org/latest/$PACKAGE" + PO_URL="$PACKAGE_PO_URL_BASE/$d.po" + PO_FILENAME="$PACKAGE.$d.po" + if wget -q -nc -O $PO_FILENAME $PO_URL; then + # we want all .po files in UTF-8 format really, so convert if needed.. + CHARSET=`grep Content-Type $PO_FILENAME | sed -e 's/.*charset=\(.*\)\\\\n.*/\1/'` + if test "x$CHARSET" != "xUTF-8" -a "x$CHARSET" != "xutf-8"; then + # note: things like the bugs address will be added back by make update-po + if msguniq $PO_FILENAME --no-location \ + --output-file=$PO_FILENAME.utf8 \ + --to-code=UTF-8; then + mv $PO_FILENAME.utf8 $PO_FILENAME + else + echo "**** $d: conversion from $CHARSET to UTF-8 failed ****" + fi + fi + if [ -f "po/$d.po" ]; then + # ./po/foo.po exists, so let's check if ours matches the latest from the + # translation project website + REVDATE_NEW=`grep PO-Revision-Date $PO_FILENAME`; + REVDATE_OLD=`grep PO-Revision-Date po/$d.po`; + CHARSET_OLD=`grep Content-Type po/$d.po | sed -e 's/.*charset=\(.*\)\\\\n.*/\1/'` + if test "x$REVDATE_NEW" = "x$REVDATE_OLD" -a "x$CHARSET_OLD" = "xUTF-8"; then + # note: source code line markers will be removed later by make upload-po + echo "$d.po: up-to-date" + rm -f $PO_FILENAME + else + mv $PO_FILENAME "po/$d.po" + if test "x$CHARSET_OLD" != "xUTF-8" -a "x$CHARSET_OLD" != "xutf-8"; then + echo "$d.po: update (and charset converted from $CHARSET_OLD to UTF-8)" + else + echo "$d.po: updated" + fi + DOMAINS_UPDATED="$DOMAINS_UPDATED $d" + fi + # make sure domain is listed in LINGUAS + if ! grep $d "po/LINGUAS" >/dev/null 2>/dev/null; then + DOMAINS_NOT_IN_LINGUAS="$DOMAINS_NOT_IN_LINGUAS $d" + fi + else + # ./po/foo.po doesn't exist, but foo.po exists on the translation project + # website, so it's probably a new translation + echo "$d.po: new language" + mv $PO_FILENAME "po/$d.po" + DOMAINS_UPDATED="$DOMAINS_UPDATED $d" + DOMAINS_TO_ADD="$DOMAINS_TO_ADD $d" + fi + else + rm -f $PO_FILENAME + echo "$d.po: failure (does probably not exist)" + fi +done + +if [ -n "$DOMAINS_UPDATED" ]; then + echo "====================================================================" + echo + echo "Language domains updated :$DOMAINS_UPDATED" + echo "Language domains to git add :$DOMAINS_TO_ADD" + echo + echo "Source: http://translationproject.org/latest/$PACKAGE/" + echo + if [ -n "$DOMAINS_TO_ADD" ]; then + CMD_STRING="git add" + for d in $DOMAINS_TO_ADD; do + CMD_STRING="$CMD_STRING po/$d.po" + done + echo "Please run" + echo + echo " $CMD_STRING" + echo + echo "now and add the following domains to the po/LINGUAS file:" + echo + echo " $DOMAINS_TO_ADD" + echo + echo + fi + echo "====================================================================" +fi + +if [ -n "$DOMAINS_NOT_IN_LINGUAS" ]; then + echo + echo "Existing domains missing from the po/LINGUAS file:" + echo + echo " $DOMAINS_NOT_IN_LINGUAS" + echo + echo +fi + + diff --git a/common/extract-release-date-from-doap-file b/common/extract-release-date-from-doap-file new file mode 100755 index 0000000..f57e307 --- /dev/null +++ b/common/extract-release-date-from-doap-file @@ -0,0 +1,32 @@ +#!/bin/sh +# Shell script to extract the date given a release version and a .doap file + +if test "x$1" = "x" -o "x$2" = "x" -o ! -s "$2"; then + echo "Usage: $0 RELEASE-VERSION-NUMBER DOAP-FILE" >&2; + exit 1 +fi + +if ! grep '/dev/null ; then + echo "$2 does not look lika a .doap file" >&2; + exit 1 +fi + +if ! grep "$1" "$2" >/dev/null ; then + echo "$2 contains no reference to a version $1" >&2; + exit 1 +fi + +awk 'BEGIN {x=0} +{ +if ( $0 ~ // ) {x=1; chunk=""} +if (x==1) { + if ($0 ~ //) { chunk = chunk $0 } + if ($0 ~ //) { chunk = chunk $0 } +} +if ($0 ~ /<\/release>/) {x=0; print chunk} +}' < "$2" | \ +\ +grep ''"$1"'' | \ +\ +sed -e 's/^.*//' -e 's/<\/created>.*$//' + diff --git a/common/gettext.patch b/common/gettext.patch new file mode 100644 index 0000000..682b905 --- /dev/null +++ b/common/gettext.patch @@ -0,0 +1,12 @@ +--- po/Makefile.in.in.orig 2006-01-07 12:03:45.000000000 +0100 ++++ po/Makefile.in.in 2006-01-07 12:04:23.000000000 +0100 +@@ -11,6 +11,9 @@ + PACKAGE = @PACKAGE@ + VERSION = @VERSION@ + ++# thomas: add GETTEXT_PACKAGE substitution as used in Makevars ++GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ ++ + SHELL = /bin/sh + @SET_MAKE@ + diff --git a/common/glib-gen.mak b/common/glib-gen.mak new file mode 100644 index 0000000..ef93a5f --- /dev/null +++ b/common/glib-gen.mak @@ -0,0 +1,44 @@ +# these are the variables your Makefile.am should set +# the example is based on the colorbalance interface + +#glib_enum_headers=$(colorbalance_headers) +#glib_enum_define=GST_COLOR_BALANCE +#glib_enum_prefix=gst_color_balance + +enum_headers=$(foreach h,$(glib_enum_headers),\n\#include \"$(h)\") + +# these are all the rules generating the relevant files +%-marshal.h: %-marshal.list + $(AM_V_GEN)glib-genmarshal --header --prefix=$(glib_enum_prefix)_marshal $^ > $*-marshal.h.tmp && \ + mv $*-marshal.h.tmp $*-marshal.h + +%-marshal.c: %-marshal.list + $(AM_V_GEN)echo "#include \"$*-marshal.h\"" >> $*-marshal.c.tmp && \ + glib-genmarshal --body --prefix=$(glib_enum_prefix)_marshal $^ >> $*-marshal.c.tmp && \ + mv $*-marshal.c.tmp $*-marshal.c + +%-enumtypes.h: $(glib_enum_headers) + $(AM_V_GEN)glib-mkenums \ + --fhead "#ifndef __$(glib_enum_define)_ENUM_TYPES_H__\n#define __$(glib_enum_define)_ENUM_TYPES_H__\n\n#include \n\nG_BEGIN_DECLS\n" \ + --fprod "\n/* enumerations from \"@filename@\" */\n" \ + --vhead "GType @enum_name@_get_type (void);\n#define GST_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __$(glib_enum_define)_ENUM_TYPES_H__ */" \ + $^ > $@ + +%-enumtypes.c: $(glib_enum_headers) + @if test "x$(glib_enum_headers)" = "x"; then echo "ERROR: glib_enum_headers is empty, please fix Makefile"; exit 1; fi + $(AM_V_GEN)glib-mkenums \ + --fhead "#include \"$*-enumtypes.h\"\n$(enum_headers)" \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static volatile gsize g_define_type_id__volatile = 0;\n if (g_once_init_enter (&g_define_type_id__volatile)) {\n static const G@Type@Value values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n GType g_define_type_id = g_@type@_register_static (\"@EnumName@\", values);\n g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);\n }\n return g_define_type_id__volatile;\n}\n" \ + $^ > $@ + +# a hack rule to make sure .Plo files exist because they get include'd +# from Makefile's +.deps/%-marshal.Plo: + @touch $@ + +.deps/%-enumtypes.Plo: + @touch $@ diff --git a/common/gst-autogen.sh b/common/gst-autogen.sh new file mode 100644 index 0000000..78cab66 --- /dev/null +++ b/common/gst-autogen.sh @@ -0,0 +1,345 @@ +# a silly hack that generates autoregen.sh but it's handy +# Remove the old autoregen.sh first to create a new file, +# as the current one may be being read by the shell executing +# this script. +if [ -f "autoregen.sh" ]; then + rm autoregen.sh +fi +echo "#!/bin/sh" > autoregen.sh +echo "./autogen.sh $@ \$@" >> autoregen.sh +chmod +x autoregen.sh + +# helper functions for autogen.sh + +debug () +# print out a debug message if DEBUG is a defined variable +{ + if test ! -z "$DEBUG" + then + echo "DEBUG: $1" + fi +} + +version_get () +# based on the command's version output, set variables +# _MAJOR, _MINOR, _MICRO, _VERSION, using the given prefix as variable prefix +# +# arg 1: command binary name +# arg 2: (uppercased) variable name prefix +{ + COMMAND=$1 + VARPREFIX=`echo $2 | tr .,- _` + local ${VARPREFIX}_VERSION + + # strip everything that's not a digit, then use cut to get the first field + pkg_version=`$COMMAND --version|head -n 1|sed 's/^.*)[^0-9]*//'|cut -d' ' -f1` + debug "pkg_version $pkg_version" + # remove any non-digit characters from the version numbers to permit numeric + # comparison + pkg_major=`echo $pkg_version | cut -d. -f1 | sed s/[a-zA-Z\-].*//g` + pkg_minor=`echo $pkg_version | cut -d. -f2 | sed s/[a-zA-Z\-].*//g` + pkg_micro=`echo $pkg_version | cut -d. -f3 | sed s/[a-zA-Z\-].*//g` + test -z "$pkg_major" && pkg_major=0 + test -z "$pkg_minor" && pkg_minor=0 + test -z "$pkg_micro" && pkg_micro=0 + debug "found major $pkg_major minor $pkg_minor micro $pkg_micro" + eval ${VARPREFIX}_MAJOR=$pkg_major + eval ${VARPREFIX}_MINOR=$pkg_minor + eval ${VARPREFIX}_MICRO=$pkg_micro + eval ${VARPREFIX}_VERSION=$pkg_version +} + +version_compare () +# Checks whether the version of VARPREFIX is equal to or +# newer than the requested version +# arg1: VARPREFIX +# arg2: MAJOR +# arg3: MINOR +# arg4: MICRO +{ + VARPREFIX=`echo $1 | tr .,- _` + MAJOR=$2 + MINOR=$3 + MICRO=$4 + + eval pkg_major=\$${VARPREFIX}_MAJOR; + eval pkg_minor=\$${VARPREFIX}_MINOR; + eval pkg_micro=\$${VARPREFIX}_MICRO; + + #start checking the version + debug "version_compare: $VARPREFIX against $MAJOR.$MINOR.$MICRO" + + # reset check + WRONG= + + if [ ! "$pkg_major" -gt "$MAJOR" ]; then + debug "major: $pkg_major <= $MAJOR" + if [ "$pkg_major" -lt "$MAJOR" ]; then + debug "major: $pkg_major < $MAJOR" + WRONG=1 + elif [ ! "$pkg_minor" -gt "$MINOR" ]; then + debug "minor: $pkg_minor <= $MINOR" + if [ "$pkg_minor" -lt "$MINOR" ]; then + debug "minor: $pkg_minor < $MINOR" + WRONG=1 + elif [ "$pkg_micro" -lt "$MICRO" ]; then + debug "micro: $pkg_micro < $MICRO" + WRONG=1 + fi + fi + fi + if test ! -z "$WRONG"; then + debug "version_compare: $VARPREFIX older than $MAJOR.$MINOR.$MICRO" + return 1 + fi + debug "version_compare: $VARPREFIX equal to/newer than $MAJOR.$MINOR.$MICRO" + return 0 +} + + +version_check () +# check the version of a package +# first argument : package name (executable) +# second argument : optional path where to look for it instead +# third argument : source download url +# rest of arguments : major, minor, micro version +# all consecutive ones : suggestions for binaries to use +# (if not specified in second argument) +{ + PACKAGE=$1 + PKG_PATH=$2 + URL=$3 + MAJOR=$4 + MINOR=$5 + MICRO=$6 + + # for backwards compatibility, we let PKG_PATH=PACKAGE when PKG_PATH null + if test -z "$PKG_PATH"; then PKG_PATH=$PACKAGE; fi + debug "major $MAJOR minor $MINOR micro $MICRO" + VERSION=$MAJOR + if test ! -z "$MINOR"; then VERSION=$VERSION.$MINOR; else MINOR=0; fi + if test ! -z "$MICRO"; then VERSION=$VERSION.$MICRO; else MICRO=0; fi + + debug "major $MAJOR minor $MINOR micro $MICRO" + + for SUGGESTION in $PKG_PATH; do + COMMAND="$SUGGESTION" + + # don't check if asked not to + test -z "$NOCHECK" && { + printf " checking for $COMMAND >= $VERSION ... " + } || { + # we set a var with the same name as the package, but stripped of + # unwanted chars + VAR=`echo $PACKAGE | sed 's/-//g'` + debug "setting $VAR" + eval $VAR="$COMMAND" + return 0 + } + + which $COMMAND > /dev/null 2>&1 + if test $? -eq 1; + then + debug "$COMMAND not found" + continue + fi + + VARPREFIX=`echo $COMMAND | sed 's/-//g' | tr [:lower:] [:upper:]` + version_get $COMMAND $VARPREFIX + + version_compare $VARPREFIX $MAJOR $MINOR $MICRO + if test $? -ne 0; then + echo "found $pkg_version, not ok !" + continue + else + echo "found $pkg_version, ok." + # we set a var with the same name as the package, but stripped of + # unwanted chars + VAR=`echo $PACKAGE | sed 's/-//g'` + debug "setting $VAR" + eval $VAR="$COMMAND" + return 0 + fi + done + + echo "$PACKAGE not found !" + echo "You must have $PACKAGE installed to compile $package." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at $URL" + return 1; +} + +aclocal_check () +{ + # normally aclocal is part of automake + # so we expect it to be in the same place as automake + # so if a different automake is supplied, we need to adapt as well + # so how's about replacing automake with aclocal in the set var, + # and saving that in $aclocal ? + # note, this will fail if the actual automake isn't called automake* + # or if part of the path before it contains it + if [ -z "$automake" ]; then + echo "Error: no automake variable set !" + return 1 + else + aclocal=`echo $automake | sed s/automake/aclocal/` + debug "aclocal: $aclocal" + if [ "$aclocal" != "aclocal" ]; + then + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-aclocal=$aclocal" + fi + if [ ! -x `which $aclocal` ]; then + echo "Error: cannot execute $aclocal !" + return 1 + fi + fi +} + +autoheader_check () +{ + # same here - autoheader is part of autoconf + # use the same voodoo + if [ -z "$autoconf" ]; then + echo "Error: no autoconf variable set !" + return 1 + else + autoheader=`echo $autoconf | sed s/autoconf/autoheader/` + debug "autoheader: $autoheader" + if [ "$autoheader" != "autoheader" ]; + then + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-autoheader=$autoheader" + fi + if [ ! -x `which $autoheader` ]; then + echo "Error: cannot execute $autoheader !" + return 1 + fi + fi + +} + +die_check () +{ + # call with $DIE + # if set to 1, we need to print something helpful then die + DIE=$1 + if test "x$DIE" = "x1"; + then + echo + echo "- Please get the right tools before proceeding." + echo "- Alternatively, if you're sure we're wrong, run with --nocheck." + exit 1 + fi +} + +autogen_options () +{ + if test "x$1" = "x"; then + return 0 + fi + + while test "x$1" != "x" ; do + optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + case "$1" in + --noconfigure) + NOCONFIGURE=defined + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --noconfigure" + echo "+ configure run disabled" + shift + ;; + --nocheck) + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --nocheck" + NOCHECK=defined + echo "+ autotools version check disabled" + shift + ;; + -d|--debug) + DEBUG=defined + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --debug" + echo "+ debug output enabled" + shift + ;; + -h|--help) + echo "autogen.sh (autogen options) -- (configure options)" + echo "autogen.sh help options: " + echo " --noconfigure don't run the configure script" + echo " --nocheck don't do version checks" + echo " --debug debug the autogen process" + echo + echo " --with-autoconf PATH use autoconf in PATH" + echo " --with-automake PATH use automake in PATH" + echo + echo "Any argument either not in the above list or after a '--' will be " + echo "passed to ./configure." + exit 1 + ;; + --with-automake=*) + AUTOMAKE=$optarg + echo "+ using alternate automake in $optarg" + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-automake=$AUTOMAKE" + shift + ;; + --with-autoconf=*) + AUTOCONF=$optarg + echo "+ using alternate autoconf in $optarg" + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-autoconf=$AUTOCONF" + shift + ;; + --) shift ; break ;; + *) + echo "+ passing argument $1 to configure" + CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT $1" + shift + ;; + esac + done + + for arg do CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT $arg"; done + if test ! -z "$CONFIGURE_EXT_OPT" + then + echo "+ options passed to configure: $CONFIGURE_EXT_OPT" + fi +} + +toplevel_check () +{ + srcfile=$1 + test -f $srcfile || { + echo "You must run this script in the top-level $package directory" + exit 1 + } +} + +tool_run () +{ + tool=$1 + options=$2 + run_if_fail=$3 + echo "+ running $tool $options..." + $tool $options || { + echo + echo $tool failed + eval $run_if_fail + exit 1 + } +} + +install_git_hooks () +{ + if test -d .git; then + # install pre-commit hook for doing clean commits + for hook in pre-commit; do + if test ! \( -x .git/hooks/$hook -a -L .git/hooks/$hook \); then + echo "+ Installing git $hook hook" + rm -f .git/hooks/$hook + ln -s ../../common/hooks/$hook.hook .git/hooks/$hook || { + # if we couldn't create a symbolic link, try doing a plain cp + if cp common/hooks/pre-commit.hook .git/hooks/pre-commit; then + chmod +x .git/hooks/pre-commit; + else + echo "********** Couldn't install git $hook hook **********"; + fi + } + fi + done + fi +} diff --git a/common/gst-indent b/common/gst-indent new file mode 100755 index 0000000..732b2ba --- /dev/null +++ b/common/gst-indent @@ -0,0 +1,49 @@ +#!/bin/sh +# +# Check that the code follows a consistant code style +# + +# Check for existence of indent, and error out if not present. +# On some *bsd systems the binary seems to be called gnunindent, +# so check for that first. + +version=`gnuindent --version 2>/dev/null` +if test "x$version" = "x"; then + version=`indent --version 2>/dev/null` + if test "x$version" = "x"; then + echo "GStreamer git pre-commit hook:" + echo "Did not find GNU indent, please install it before continuing." + exit 1 + fi + INDENT=indent +else + INDENT=gnuindent +fi + +case `$INDENT --version` in + GNU*) + ;; + default) + echo "GStreamer git pre-commit hook:" + echo "Did not find GNU indent, please install it before continuing." + echo "(Found $INDENT, but it doesn't seem to be GNU indent)" + exit 1 + ;; +esac + +INDENT_PARAMETERS="--braces-on-if-line \ + --case-brace-indentation0 \ + --case-indentation2 \ + --braces-after-struct-decl-line \ + --line-length80 \ + --no-tabs \ + --cuddle-else \ + --dont-line-up-parentheses \ + --continuation-indentation4 \ + --honour-newlines \ + --tab-size8 \ + --indent-level2 \ + --leave-preprocessor-space" + +$INDENT ${INDENT_PARAMETERS} $@ + diff --git a/common/gst.supp b/common/gst.supp new file mode 100644 index 0000000..2c60392 --- /dev/null +++ b/common/gst.supp @@ -0,0 +1,3967 @@ +### this file contains suppressions for valgrind when running +### the gstreamer unit tests +### it might be useful for wider use as well + +### syscall suppressions + +{ + + Memcheck:Param + clone(parent_tidptr) + fun:clone + fun:clone +} + +{ + + Memcheck:Param + clone(child_tidptr) + fun:clone + fun:clone +} + +{ + + Memcheck:Param + clone(tlsinfo) + fun:clone + fun:clone +} + +### glibc suppressions + +{ + + Memcheck:Cond + obj:/lib/ld-2.*.so + fun:dl_open_worker + obj:/lib/ld-2.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.*.so + fun:_dlerror_run + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_file +} + +{ + + Memcheck:Cond + fun:strlen + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start + obj:/lib64/ld-2.*.so + obj:* + obj:* +} + +{ + + Memcheck:Cond + fun:_dl_relocate_object + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start +} + +{ + + Memcheck:Cond + fun:* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +# glibc does not deallocate thread-local storage + +{ + + Memcheck:Leak + fun:calloc + fun:_dl_allocate_tls + fun:pthread_create@@* +} + +{ + + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls +} + +# I get an extra stack entry on x86/dapper +{ + + Memcheck:Leak + fun:calloc + obj:/lib/ld-2.3.*.so + fun:_dl_allocate_tls + fun:pthread_create@@* +} + + +{ + + Memcheck:Cond + fun:strstr + fun:__pthread_initialize_minimal + obj:/lib/libpthread-*.so + obj:/lib/libpthread-*.so + fun:call_init + fun:_dl_init + obj:/lib/ld-*.so +} + +# a thread-related free problem in glibc from Edgard +{ + __libc_freeres_rw_acess + Memcheck:Addr4 + obj:* + obj:* + obj:* + obj:* + obj:* + fun:__libc_freeres +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so +} + +# g_module_open-related problems +{ + + Memcheck:Addr2 + fun:memcpy + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open + fun:gst_plugin_load_file + fun:gst_registry_scan_path_level + fun:gst_registry_scan_path_level + fun:gst_registry_scan_path_level + fun:init_post + fun:g_option_context_parse + fun:gst_init_check + fun:gst_init + fun:gst_check_init + fun:main +} + +{ + + Memcheck:Addr4 + fun:memcpy + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open + fun:gst_plugin_load_file + fun:gst_registry_scan_path_level + fun:gst_registry_scan_path_level + fun:gst_registry_scan_path_level + fun:init_post + fun:g_option_context_parse + fun:gst_init_check + fun:gst_init + fun:gst_check_init + fun:main +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:do_sym + fun:_dl_sym + fun:dlsym_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlsym + fun:g_module_symbol + fun:g_module_open + fun:gst_plugin_load_file +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open + fun:gst_plugin_load_file +} +{ + + Memcheck:Cond + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open + fun:gst_plugin_load_file + fun:gst_plugin_load_by_name + fun:gst_plugin_feature_load +} + +{ + + Memcheck:Leak + fun:malloc + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open + fun:gst_plugin_load_file + fun:gst_plugin_load_by_name +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:do_sym + fun:_dl_sym + fun:dlsym_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlsym + fun:g_module_symbol + fun:g_module_open +} + +{ + + Memcheck:Param + futex(uaddr2) + fun:pthread_once + obj:/lib/libc-2.3.*.so + obj:/lib/libc-2.3.*.so + fun:mbsnrtowcs + fun:vfprintf + fun:vsprintf + fun:sprintf + obj:/lib/libc-2.3.*.so + fun:tmpfile + fun:setup_pipe + fun:setup_messaging_with_key + fun:setup_messaging +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + fun:_dl_sym + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlsym + fun:g_module_symbol + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + fun:iconv_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + fun:iconv_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + fun:iconv_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + fun:iconv_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +# suppression for a glibc bug: +# http://valgrind.org/docs/manual/faq.html#faq.exit_errors> +{ + + Memcheck:Free + fun:free + obj:*libc-*.so + fun:__libc_freeres + fun:* + fun:_Exit +} + +# same as above, just so it works for tpm on gutsy/x86-64 +{ + + Memcheck:Free + fun:free + fun:free_mem + fun:__libc_freeres +} + +# valgrind doesn't allow me to specify a suppression for Addr1, Addr2, Addr4 +# as Addr*, so 3 copies for that; and then 2 of each for that pesky memcpy +{ + + Memcheck:Addr1 + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr2 + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} +{ + + Memcheck:Addr4 + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr1 + fun:memcpy + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr2 + fun:memcpy + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} +{ + + Memcheck:Addr4 + fun:memcpy + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/libc-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:_dl_open + obj:/lib/libdl-2.3.*.so + obj:/lib/ld-2.3.*.so +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.*.so + obj:/lib/libc-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:_dl_open + obj:/lib/libdl-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/libdl-2.3.*.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_file + fun:gst_plugin_load_by_name + fun:gst_plugin_feature_load +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libc-2.3.6.so + obj:/lib/ld-2.3.6.so + fun:_dl_open + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libc-2.3.6.so + obj:/lib/ld-2.3.6.so + fun:_dl_open + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libc-2.3.6.so + obj:/lib/ld-2.3.6.so + fun:_dl_open + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + fun:dlopen +} + +### glib suppressions +{ + + Memcheck:Cond + fun:g_parse_debug_string + obj:/usr/lib*/libglib-2.0.so.* + fun:g_slice_alloc + fun:g_slice_alloc0 +} + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:g_type_init* + fun:init_pre* +} + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:g_type_register_fundamental +} + +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:type_node_any_new_W +} + +{ + + Memcheck:Leak + fun:realloc + fun:g_realloc + fun:type_node_any_new_W +} + +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:g_type_class_ref +} + +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:type_add_flags_W +} + +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:type_add_flags_W +} + +#pthread memleaks + +{ + Thread creation leak + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate* + fun:_dl_allocate* + fun:__pthread_initialize_minimal +} + +{ + Thread management leak + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate* + fun:_dl_allocate* + fun:__pthread_* +} + +{ + Thread management leak 2 + Memcheck:Leak + fun:memalign + fun:_dl_allocate* + fun:_dl_allocate* + fun:__pthread_* +} + +{ + pthread_create Syscall param write(buf) points to uninitialised byte(s) + Memcheck:Param + write(buf) + fun:pthread_create@@GLIBC_2.2.5 + fun:g_thread_create* + +} + +# nss_parse_* memleak (used by g_option_context_parse) +{ + nss_parse_* memleak + Memcheck:Leak + fun:malloc + fun:nss_parse_service_list + fun:__nss_database_lookup +} + +# liboil suppressions +{ + + Memcheck:Value8 + obj:/usr/lib/liboil-0.3.so.0.1.0 + obj:/usr/lib/liboil-0.3.so.0.1.0 + obj:/usr/lib/liboil-0.3.so.0.1.0 + fun:oil_cpu_fault_check_try + fun:oil_test_check_impl + fun:oil_class_optimize + fun:oil_optimize_all + fun:oil_init +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.3.6.so +} + +{ + + Memcheck:Param + futex(uaddr2) + fun:pthread_once + obj:/lib/libc-2.3.6.so + obj:/lib/libc-2.3.6.so + fun:setlocale + fun:init_pre + fun:g_option_context_parse + fun:gst_init_check + fun:gst_init + fun:gst_check_init + fun:main +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.6.so + obj:/lib/ld-2.3.6.so + fun:_dl_open + obj:/lib/libdl-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/libdl-2.3.6.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_file +} +# this exists in a bunch of different variations, hence the short tail/trace +{ + + Memcheck:Addr4 + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so +} +{ + + Memcheck:Addr8 + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so +} + +# More edgy suppressions (Mike) +{ + + Memcheck:Cond + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + fun:dlopen_doit + obj:/lib/ld-2.4.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + fun:dlopen_doit + obj:/lib/ld-2.4.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + fun:do_sym + fun:_dl_sym +} + +# This one's overly general, but there's zero other information in the stack +# trace - just these five lines! +{ + + Memcheck:Cond + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so +} + +{ + + Memcheck:Leak + fun:calloc + obj:/lib/ld-2.4.so + fun:_dl_allocate_tls + fun:pthread_create@@GLIBC_2.1 +} + +# TLS leaks for feisty/x86 +{ + + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls + fun:pthread_create@@GLIBC_2.1 +} + +{ + + Memcheck:Leak + fun:calloc + obj:/usr/lib/libcdio.so.6.0.1 + fun:cdio_open_am_linux + obj:/usr/lib/libcdio.so.6.0.1 + fun:cdio_open_am +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.5.so +} + +{ + + Memcheck:Cond + fun:snd_pcm_direct_shm_create_or_connect + fun:snd_pcm_dsnoop_open + fun:_snd_pcm_dsnoop_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_plug_open + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_asym_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 +} + +{ + + Memcheck:Cond + fun:snd*_pcm_hw_param_set_near +} + +{ + + Memcheck:Cond + ... + fun:snd*_pcm_hw_param_set_near +} + +{ + + Memcheck:Cond + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_close + obj:/*lib/libasound.so.2.0.0 +} +{ + + Memcheck:Cond + fun:snd_pcm_direct_shm_create_or_connect + fun:snd_pcm_dmix_open + fun:_snd_pcm_dmix_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_softvol_open + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_plug_open + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_asym_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 +} +{ + + Memcheck:Leak + fun:malloc + fun:strdup + fun:snd_dlobj_cache_add + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:snd_pcm_dsnoop_open + fun:_snd_pcm_dsnoop_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_plug_open + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_asym_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 +} +# Catch about 15 variations on inserting info into an ALSA +# internal cache +{ + + Memcheck:Leak + fun:malloc + ... + fun:snd*_dlobj_cache_add + obj:/*lib*/libasound.so.2.0.0 +} + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:snd_pcm_open_conf +} + +{ + + Memcheck:Leak + fun:*alloc + obj:/*lib*/libasound.so.2.0.0 + ... + fun:snd_config_hook_load +} + +{ + + Memcheck:Leak + fun:*alloc + obj:/*lib*/libasound.so.2.0.0 + ... + fun:snd_config_update_r + fun:snd_config_update +} +{ + + Memcheck:Leak + fun:*alloc + fun:strdup + ... + fun:snd_config_update_r + fun:snd_config_update +} +{ + + Memcheck:Leak + fun:*alloc + fun:_dl_close_worker + ... + fun:snd_config_searcha_hooks +} + +{ + + Memcheck:Leak + fun:malloc + obj:/lib/libc*.so + fun:__nss_database_lookup + obj:* + obj:* + fun:getgrnam_r + fun:getgrnam + fun:snd_pcm_direct_parse_open_conf +} + +{ + + Memcheck:Leak + fun:calloc + fun:_XCBInitDisplayLock + fun:XOpenDisplay +} + +# GConf internal initialisations related to getting the default client. +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_tcval + obj:/usr/lib/libORBit-2.so.* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:CORBA_ORB_string_to_object + obj:/usr/lib/libgconf-2.so.* + fun:gconf_get_current_lock_holder + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so.* + obj:/usr/lib/libgconf-2.so.* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_tcval + obj:* + fun:PortableServer_POA_servant_to_reference + fun:* + fun:* + fun:* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_tcval + obj:/usr/lib/libORBit-2.so.* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:CORBA_ORB_string_to_object + obj:/usr/lib/libgconf-2.so.* + fun:gconf_get_current_lock_holder + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so.* + obj:/usr/lib/libgconf-2.so.* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:ORBit_demarshal_value + fun:* + fun:ORBit_small_invoke_stub + fun:ConfigServer_get_default_database + fun:* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:* + fun:IOP_generate_profiles + fun:ORBit_marshal_object + fun:ORBit_marshal_value + fun:* + fun:ORBit_small_invoke_stub + fun:ConfigServer_add_client + fun:* + fun:* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_by_tc + fun:* + fun:PortableServer_POA_servant_to_reference + fun:* + fun:* + fun:* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_by_tc + obj:/usr/lib/libORBit-2.so.* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:CORBA_ORB_string_to_object + obj:/usr/lib/libgconf-2.so.* + fun:gconf_get_current_lock_holder + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so.* + obj:/usr/lib/libgconf-2.so.* + fun:gconf_engine_get_default +} + +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:* + fun:* + fun:gconf_activate_server +} + +# Some libORBit/bonobo initialisation stuff +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:ORBit_alloc_string + fun:CORBA_string_dup + fun:Bonobo_ActivationEnvValue_set + fun:bonobo_activation_init_activation_env + fun:bonobo_activation_orb_init + fun:bonobo_activation_init +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc* + obj:/usr/lib/libORBit-2.so* + fun:PortableServer_POA_servant_to_reference + obj:/usr/lib/libbonobo-2.so* +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_tcval + fun:ORBit_small_allocbuf + fun:ORBit_adaptor_setup + obj:/usr/lib/libORBit-2.so* + fun:ORBit_POA_setup_root + fun:ORBit_init_internals + fun:CORBA_ORB_init +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_tcval + fun:ORBit_adaptor_setup + fun:* + fun:ORBit_POA_setup_root + fun:ORBit_init_internals + fun:CORBA_ORB_init +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_allocbuf + fun:bonobo_activation_init_activation_env + fun:bonobo_activation_orb_init + fun:bonobo_activation_init +} + +# More GConf stuff from the FC5 buildbot, mostly variations on the +# above stack traces +{ + + Memcheck:Param + writev(vector[...]) + fun:writev + obj:/usr/lib/libORBit-2.so* + fun:link_connection_writev + fun:giop_send_buffer_write + obj:/usr/lib/libORBit-2.so* + fun:ORBit_small_invoke_stub + fun:ORBit_small_invoke_stub_n + fun:ORBit_c_stub_invoke + fun:ConfigServer_ping + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc* + obj:/usr/lib/libORBit-2.so* + fun:PortableServer_POA_servant_to_reference + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc + obj:/usr/lib/libORBit-2.so* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:CORBA_ORB_string_to_object + obj:/usr/lib/libgconf-2.so* + fun:gconf_get_current_lock_holder + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc* + obj:/usr/lib/libORBit-2.so* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:CORBA_ORB_string_to_object + obj:/usr/lib/libgconf-2.so* + fun:gconf_get_current_lock_holder + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc* + obj:/usr/lib/libORBit-2.so* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:ORBit_demarshal_value + obj:/usr/lib/libORBit-2.so* + fun:ORBit_small_invoke_stub + fun:ORBit_small_invoke_stub_n + fun:ORBit_c_stub_invoke + fun:ConfigServer_get_default_database + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc* + obj:/usr/lib/libORBit-2.so* + fun:ORBit_OAObject_object_to_objkey + fun:IOP_generate_profiles + fun:ORBit_marshal_object + fun:ORBit_marshal_value + obj:/usr/lib/libORBit-2.so* + fun:ORBit_small_invoke_stub + fun:ORBit_small_invoke_stub_n + fun:ORBit_c_stub_invoke + fun:ConfigServer_add_client + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:malloc + obj:*libc-*.so + fun:__nss_database_lookup + obj:* + obj:* + fun:getpwnam_r + obj:/usr/lib*/libglib-2.0.so.* + fun:g_get_home_dir +} +{ + + Memcheck:Leak + fun:malloc + obj:*libc-*.so + fun:__nss_database_lookup + obj:* + obj:* + fun:getpwnam_r + obj:/usr/lib*/libglib-2.0.so.* + fun:g_get_user_name +} +{ + + Memcheck:Leak + fun:malloc + obj:*libc-*.so + fun:__nss_database_lookup + obj:* + obj:* + fun:getpwnam_r + obj:/usr/lib*/libglib-2.0.so.* + fun:g_get_tmp_dir +} + +{ + + Memcheck:Leak + fun:malloc + obj:*libc-*.so + fun:__nss_database_lookup + obj:* + obj:* + fun:getpwnam_r + obj:/usr/lib*/libglib-2.0.so.0.* + fun:g_get_host_name +} + + +## Some Fontconfig errors. +{ + + Memcheck:Leak + fun:malloc + fun:FcPatternObjectInsertElt + fun:FcPatternObjectAddWithBinding + fun:FcPatternAppend + fun:FcEndElement + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + fun:XML_ParseBuffer + fun:FcConfigParseAndLoad + fun:FcConfigParseAndLoad + fun:FcParseInclude + fun:FcEndElement + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + fun:XML_ParseBuffer + fun:FcConfigParseAndLoad +} +{ + + Memcheck:Leak + fun:*alloc + ... + fun:FcInitLoadConfig +} + +# Issues with ubuntu Hardy, same crack as for previous ubuntus +{ + + Memcheck:Leak + fun:calloc + obj:* + fun:_dl_allocate_tls + fun:pthread_create@@* + obj:/usr/lib/libgthread* + fun:g_thread_* +} + +# I've made this version generic, so that it covers future modifications +# of library names +{ + + Memcheck:Leak + fun:calloc + obj:* + fun:_dl_allocate_tls + fun:pthread_create@@* + fun:g_thread_* +} + +# series of invalid read of size 4 in g_module_open for ubuntu +# hardy x86/32bit +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_* +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_* +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_* +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_* +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load* +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libc-2.7.so + fun:_dl_sym + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlsym + fun:g_module_symbol + fun:g_module_open + fun:gst_plugin_load_* +} + +# series of invalid read of size 8 in g_module_open for ubuntu +# hardy x86/64bit +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlsym + fun:g_module_symbol + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + fun:__nss_lookup_function + obj:/lib/tls/i686/cmov/libc-2.7.so + fun:__nss_passwd_lookup + fun:getpwnam_r +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + fun:__nss_lookup_function + obj:/lib/tls/i686/cmov/libc-2.7.so + fun:__nss_passwd_lookup + fun:getpwnam_r +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + fun:__nss_lookup_function + obj:/lib/tls/i686/cmov/libnss_compat-2.7.so + fun:_nss_compat_getpwnam_r + fun:getpwnam_r +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + fun:__nss_lookup_function + obj:/lib/tls/i686/cmov/libnss_compat-2.7.so + fun:_nss_compat_getpwnam_r + fun:getpwnam_r +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + fun:__nss_lookup_function + obj:/lib/libc-2.7.so + fun:getpwnam_r +} + +## Leaks in ALSA (variations of leak from snd_config_load1) + +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:snd_config_load1 +} +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:snd_config_load1 +} +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:malloc + fun:snd1_dlobj_cache_add + fun:snd_ctl_open_noupdate +} + +{ + + Memcheck:Leak + fun:malloc + fun:* + fun:snd1_dlobj_cache_add + fun:snd_ctl_open_noupdate +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + + +# The following are leaks of caps that need to be created dynamically +# in the type registration of the plugin (used for pad templates). + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_new_simple + fun:* + fun:g_type_class_ref + fun:gst_element_register +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:* + fun:* + fun:g_type_class_ref + fun:gst_element_register + fun:gst_ogm_parse_plugin_init + fun:plugin_init +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_copy + fun:gst_video_test_src_base_init + fun:g_type_class_ref + fun:gst_element_register +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_copy + fun:gst_video_test_src_getcaps + fun:gst_video_test_src_base_init + fun:g_type_class_ref + fun:gst_element_register +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_ffmpegcsp_codectype_to_caps + fun:gst_ffmpegcolorspace_register + fun:plugin_init +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_copy + fun:gst_ffmpegcolorspace_register + fun:plugin_init +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_new_any + fun:gst_ffmpegdemux_register + fun:plugin_init +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} + +{ + + Memcheck:Leak + fun:realloc + fun:g_realloc + fun:g_ptr_array_maybe_expand + fun:g_ptr_array_add + fun:gst_caps_append + fun:gst_audio_filter_class_add_pad_templates +} + +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:g_ptr_array_maybe_expand + fun:g_ptr_array_add + fun:gst_caps_append + fun:gst_audio_filter_class_add_pad_templates +} + +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:g_ptr_array_maybe_expand + fun:g_ptr_array_add + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:g_ptr_array_sized_new + fun:gst_caps_new_empty + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:g_array_maybe_expand + fun:g_array_sized_new + fun:* + fun:* + fun:* + fun:gst_value_init_and_copy + fun:gst_structure_copy + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:g_array_maybe_expand + fun:g_array_sized_new + fun:* + fun:gst_structure_copy + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:g_array_sized_new + fun:* + fun:gst_structure_copy + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_riff_create_*_template_caps +} +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:* + fun:* + fun:* + fun:gst_structure_copy + fun:gst_caps_copy + fun:gst_caps_append + fun:gst_riff_create_*_template_caps +} +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:g_array_sized_new + fun:* + fun:gst_structure_copy + fun:gst_caps_copy + fun:gst_caps_append + fun:gst_riff_create_*_template_caps +} + +## Leaks in pango (bilboed: gentoo unstable amd64) + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:pango_layout_get_pixel_extents +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:pango_language_from_string + fun:pango_language_get_default + fun:pango_context_init + fun:g_type_create_instance + fun:g_object_constructor + fun:g_object_newv + fun:g_object_new_valist + fun:g_object_new + fun:pango_font_map_create_context +} + +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:pango_language_from_string +} + + +## Leak of everything allocated by gst-libav plugin init +{ + + Memcheck:Leak + fun:*alloc + ... + fun:gst_ffmpeg_cfg_init +} + +## Leak of GIO module through gnomevfs + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:* + fun:* + fun:g_type_create_instance + fun:* + fun:* + fun:* + fun:* + fun:g_io_module_new + fun:g_io_modules_load_all_in_directory + fun:* + fun:get_default_vfs +} + +## Conditional jump in getaddrinfo (bilboed, gentoo ~amd64, Dec 13 2008) +{ + + Memcheck:Cond + fun:gaih_inet + fun:getaddrinfo +} + +## Dynamic pad templates in mxfmux +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_from_string + fun:mxf_*_init + fun:plugin_init +} + +## We don't know if ffmpeg frees this or not and better pass a copy for safety +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_strdup + fun:gst_ffmpeg_cfg_fill_context + fun:gst_ffmpegenc_setcaps + fun:gst_pad_set_caps +} + +## Leak/overreads with glibc-2.10 + +{ + + Memcheck:Value8 + fun:do_sym + fun:dlsym_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlsym +} +{ + + Memcheck:Cond + fun:do_sym + fun:dlsym_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlsym +} + +{ + + Memcheck:Value8 + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Value8 + fun:_dl_relocate_object + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Value8 + fun:_dl_check_map_versions + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Cond + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Cond + fun:_dl_relocate_object + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Cond + fun:_dl_check_map_versions + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Cond + fun:_dl_map_object* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Value8 + fun:_dl_map_object* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Value8 + fun:_dl_check_caller + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Cond + fun:_dl_check_caller + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Value8 + obj:/lib*/libc-2.10.*.so + obj:/lib*/libc-2.10.*.so + fun:_vgnU_freeres +} +{ + + Memcheck:Cond + obj:/lib*/libc-2.10.*.so + obj:/lib*/libc-2.10.*.so + fun:_vgnU_freeres +} +{ + + Memcheck:Free + fun:free + obj:/lib*/libc-2.10.*.so + obj:/lib*/libc-2.10.*.so + fun:_vgnU_freeres +} + +{ + + Memcheck:Value8 + fun:_dl_fini + fun:__run_exit_handlers + fun:exit +} + +{ + + Memcheck:Cond + fun:_dl_fini + fun:__run_exit_handlers + fun:exit +} +{ + + Memcheck:Value8 + fun:_dl_sort_fini + fun:_dl_fini + fun:__run_exit_handlers + fun:exit +} + +{ + + Memcheck:Cond + fun:_dl_sort_fini + fun:_dl_fini + fun:__run_exit_handlers + fun:exit +} + +# glibc-2.10 dl overreads +{ + + Memcheck:Value8 + fun:_dl_fixup + fun:_dl_runtime_resolve +} +{ + + Memcheck:Cond + fun:_dl_fixup + fun:_dl_runtime_resolve +} + +{ + + Memcheck:Value8 + fun:_dl_lookup_symbol_x + fun:_dl_fixup + fun:_dl_runtime_resolve +} +{ + + Memcheck:Cond + fun:_dl_lookup_symbol_x + fun:_dl_fixup + fun:_dl_runtime_resolve +} +{ + + Memcheck:Value8 + fun:call_init + fun:_dl_init +} +{ + + Memcheck:Value8 + fun:_dl_init +} +{ + + Memcheck:Value8 + fun:do_lookup_x + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} +{ + + Memcheck:Cond + fun:do_lookup_x + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} +{ + + Memcheck:Value8 + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} +{ + + Memcheck:Value8 + fun:_dl_relocate_object + fun:dl_main +} +{ + + Memcheck:Value8 + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start +} +{ + + Memcheck:Cond + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start +} + +{ + + Memcheck:Cond + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_check_map_versions + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} + +{ + + Memcheck:Cond + fun:_dl_check_map_versions + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} + +{ + + Memcheck:Cond + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_check_map_versions + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} +{ + + Memcheck:Cond + fun:* + fun:_dl_check_map_versions + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:init_tls + fun:dl_main +} +{ + + Memcheck:Cond + fun:init_tls + fun:dl_main +} + +{ + + Memcheck:Cond + fun:_dl_map_object_deps + fun:dl_main +} +{ + + Memcheck:Value8 + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_protect_relro + fun:_dl_relocate_object + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_setup_hash + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:* + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:* + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Cond + fun:* + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:open_path + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Cond + fun:* + fun:open_path + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_name_match_p + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:* + fun:* + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_name_match_p + fun:_dl_check_map_versions + fun:_dl_check_all_versions +} + +{ + + Memcheck:Value8 + fun:* + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x +} + +{ + + Memcheck:Cond + fun:do_lookup_x + fun:_dl_lookup_symbol_x +} + +{ + + Memcheck:Value8 + fun:do_lookup_x + fun:_dl_lookup_symbol_x +} + +{ + + Memcheck:Value8 + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x +} +{ + + Memcheck:Cond + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x +} + +{ + + Memcheck:Value8 + fun:_dl_name_match_p + fun:_dl_map_object + fun:dl_open_worker +} +{ + + Memcheck:Cond + fun:_dl_name_match_p + fun:_dl_map_object + fun:dl_open_worker +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_name_match_p + fun:_dl_map_object + fun:dl_open_worker +} +{ + + Memcheck:Cond + fun:* + fun:_dl_name_match_p + fun:_dl_map_object + fun:dl_open_worker +} + +{ + + Memcheck:Value8 + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object +} +{ + + Memcheck:Cond + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object +} + +{ + + Memcheck:Value8 + fun:* + fun:* + fun:_dl_check_map_versions +} +{ + + Memcheck:Value8 + fun:* + fun:_dl_check_map_versions +} +{ + + Memcheck:Cond + fun:* + fun:* + fun:_dl_check_map_versions +} +{ + + Memcheck:Cond + fun:* + fun:_dl_check_map_versions +} +{ + + Memcheck:Value8 + fun:openaux +} +{ + + Memcheck:Value8 + fun:_dl_name_match_p + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:_dl_close_worker + fun:_dl_close + fun:_dl_catch_error + fun:dlerror_run +} +{ + + Memcheck:Value8 + fun:_dl_close_worker + fun:_dl_close + fun:_dl_catch_error + fun:dlerror_run +} +{ + + Memcheck:Cond + fun:* + fun:_dl_close_worker + fun:_dl_close + fun:_dl_catch_error + fun:dlerror_run +} +{ + + Memcheck:Value8 + fun:* + fun:_dl_close_worker + fun:_dl_close + fun:_dl_catch_error + fun:dlerror_run +} + +{ + + Memcheck:Cond + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main +} +{ + + Memcheck:Value8 + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main +} +{ + + Memcheck:Cond + fun:* + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main +} +{ + + Memcheck:Value8 + fun:* + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main +} + +{ + + Memcheck:Cond + fun:_dl_map_object + fun:map_doit + fun:_dl_catch_error + fun:do_preload + fun:dl_main +} +{ + + Memcheck:Value8 + fun:_dl_map_object + fun:map_doit + fun:_dl_catch_error + fun:do_preload + fun:dl_main +} +{ + + Memcheck:Param + open(filename) + fun:open + fun:open_verify + fun:_dl_map_object + fun:map_doit + fun:_dl_catch_error + fun:do_preload + fun:dl_main +} + +{ + + Memcheck:Param + stat(file_name) + fun:_xstat + fun:open_path + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_open_worker +} + +{ + + Memcheck:Cond + fun:* + fun:_dl_map_object_deps + fun:dl_main +} +{ + + Memcheck:Value8 + fun:* + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:* + fun:_dl_map_object_deps + fun:dl_main +} + +# glibc-2.10 tls issues +{ + + Memcheck:Cond + fun:* + fun:init_tls + fun:dl_main +} +{ + + Memcheck:Value8 + fun:* + fun:init_tls + fun:dl_main +} +{ + + Memcheck:Cond + fun:* + fun:* + fun:init_tls + fun:dl_main +} +{ + + Memcheck:Value8 + fun:* + fun:* + fun:init_tls + fun:dl_main +} + +{ + + Memcheck:Cond + fun:_dl_allocate_tls_init + fun:dl_main +} +{ + + Memcheck:Value8 + fun:_dl_allocate_tls_init + fun:dl_main +} +{ + + Memcheck:Cond + fun:* + fun:_dl_allocate_tls_init + fun:dl_main +} +{ + + Memcheck:Value8 + fun:* + fun:_dl_allocate_tls_init + fun:dl_main +} + +{ + + Memcheck:Cond + fun:__tls* + obj:* + obj:* + fun:_vgnU_freeres +} + +{ + + Memcheck:Param + arch_prctl(arg2) + fun:init_tls +} +# GLib caching tmp/home directories (glibc-2.10 variants) +{ + + Memcheck:Cond + fun:* + fun:dl_open_worker + fun:* + fun:* + fun:* + fun:_dl_catch_error + fun:dlerror_run + fun:* + fun:__nss_lookup_function + fun:__nss_lookup + fun:getpwnam* +} +{ + + Memcheck:Value8 + fun:* + fun:dl_open_worker + fun:* + fun:* + fun:* + fun:_dl_catch_error + fun:dlerror_run + fun:* + fun:__nss_lookup_function + fun:__nss_lookup + fun:getpwnam* +} +{ + + Memcheck:Cond + fun:dl_open_worker + fun:* + fun:* + fun:do_dlopen + fun:* + fun:dlerror_run + fun:* + fun:__nss_lookup_function + fun:__nss_lookup + fun:getpwnam* +} +{ + + Memcheck:Value8 + fun:dl_open_worker + fun:* + fun:* + fun:do_dlopen + fun:* + fun:dlerror_run + fun:* + fun:__nss_lookup_function + fun:__nss_lookup + fun:getpwnam* +} + +{ + + Memcheck:Value8 + fun:_dl_add_to_slotinfo + fun:dl_main +} +{ + + Memcheck:Param + open(filename) + fun:open + fun:open_verify + fun:open_path + fun:_dl_map_object +} + + + +# GModule issues with glibc-2.10 +{ + + Memcheck:Value8 + fun:* + fun:* + fun:dlsym + fun:g_module_symbol +} +{ + + Memcheck:Value8 + fun:g_module_* + fun:gst_plugin* +} +{ + + Memcheck:Value8 + fun:* + fun:g_module_* + fun:gst_plugin* +} + +{ + + Memcheck:Value8 + fun:* + fun:* + fun:dlopen* + fun:g_module_open +} +{ + + Memcheck:Value8 + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:dlsym + fun:g_module_symbol +} + +{ + + Memcheck:Value8 + fun:* + fun:* + fun:* + fun:* + fun:* + fun:dlopen* + fun:g_module_open +} + +# Leak in GSlice +{ + + Memcheck:Value8 + fun:g_parse_debug_string + fun:slice_config_init + fun:g_slice_init_nomessage + fun:_g_slice_thread_init_nomessage + fun:g_thread_init_glib +} + +# 2.10 pthread issues +{ + + Memcheck:Value8 + fun:__pthread_initialize_minimal +} + +# glibc 2.11 conditional +{ + + Memcheck:Cond + fun:_dl_relocate_object + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start + obj:/lib64/ld-2.11.so +} + +# glibc 2.11 Leak + +{ + + Memcheck:Leak + fun:*alloc + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:_dl_* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:_dl_* + fun:_dl_* + fun:_dl_* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:_dl_* + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:_dl_map_object + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:_dl_* + fun:_dl_* + fun:_dl_* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +# glib type leaks +{ + + Memcheck:Leak + fun:*alloc + ... + fun:g_type_register_static +} + +# new registry system +# all of this will only be created once when loading registry. + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:_priv_gst_registry_chunks_load_plugin +} + +# system-wide tags +# these tags are registered once + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:gst_tag_register + fun:_gst_tag_initialize +} + +# system-wide type classes that we keep referenced + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:g_type_class_ref +} + +# leaking cached queries which are only initialized once +{ + + Memcheck:Leak + fun:*alloc + ... + fun:_gst_query_initialize + fun:init_post +} + +# macosx (leopard) library loader leak +{ + + Memcheck:Leak + fun:_Znwm + fun:_ZNSs4_Rep9_S_createEmmRKSaIcE + fun:_ZNSs12_S_constructIPKcEEPcT_S3_RKSaIcESt20forward_iterator_tag + fun:_ZNSsC2EPKcRKSaIcE + fun:_Z41__static_initialization_and_destruction_0ii + fun:_ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE +} + +# GObject type registration +{ + + Memcheck:Leak + fun:*alloc + ... + fun:_g_atomic_array_copy +} + +{ + + Memcheck:Leak + fun:*alloc + fun:getdelim + obj:*libselinux* +} + +{ + + Memcheck:Leak + fun:*alloc + ... + obj:*/sed +} + +{ + + Memcheck:Addr8 + ... + obj:*/sed +} + +# GLib 2.23 interface vtable +{ + + Memcheck:Leak + fun:*alloc + ... + fun:g_type_add_interface_static +} + +{ + + Memcheck:Leak + fun:*alloc + obj:*/dash +} + +# libtool/gentoo fake leak +# it actually runs bash and valgrind complains +{ + + Memcheck:Leak + fun:*alloc + obj:/bin/bash +} + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:_gst_plugin_loader_client_run + fun:main +} + +{ + + Memcheck:Cond + fun:*strcasecmp* + ... + fun:__dcigettext +} + +{ + + Memcheck:Value8 + fun:*strcasecmp* + ... + fun:__dcigettext +} + +{ + + Memcheck:Leak + fun:malloc + ... + fun:gst_poll_new + fun:gst_poll_new_timer + fun:gst_system_clock_init +} + +{ + + Memcheck:Leak + fun:calloc + ... + fun:gobject_init_ctor +} + +{ + + Memcheck:Leak + fun:malloc + ... + fun:g_quark_from*_string +} diff --git a/common/gstdoc-scangobj b/common/gstdoc-scangobj new file mode 100755 index 0000000..4ad9786 --- /dev/null +++ b/common/gstdoc-scangobj @@ -0,0 +1,1617 @@ +#!/usr/bin/env perl +# -*- cperl -*- +# +# gtk-doc - GTK DocBook documentation generator. +# Copyright (C) 1998 Damon Chaplin +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +# + +# +# This gets information about object hierarchies and signals +# by compiling a small C program. CFLAGS and LDFLAGS must be +# set appropriately before running this script. +# + +use Getopt::Long; + +my $GTK_DOC_PREFIX=`pkg-config --variable prefix gtk-doc`; +if ($GTK_DOC_PREFIX) { + chomp $GTK_DOC_PREFIX; + #print "Adding $GTK_DOC_PREFIX/share/gtk-doc/data to \@INC\n"; + unshift @INC, "$GTK_DOC_PREFIX/share/gtk-doc/data"; +} else { + unshift @INC, '/usr/share/gtk-doc/data'; +} +require "gtkdoc-common.pl"; + +# Options + +# name of documentation module +my $MODULE; +my $OUTPUT_DIR; +my $INSPECT_DIR; +my $VERBOSE; +my $PRINT_VERSION; +my $PRINT_HELP; +my $TYPE_INIT_FUNC="g_type_init ()"; + +# --nogtkinit is deprecated, as it is the default now anyway. +%optctl = (module => \$MODULE, + source => \$SOURCE, + types => \$TYPES_FILE, + nogtkinit => \$NO_GTK_INIT, + 'type-init-func' => \$TYPE_INIT_FUNC, + 'output-dir' => \$OUTPUT_DIR, + 'inspect-dir' => \$INSPECT_DIR, + 'verbose' => \$VERBOSE, + 'version' => \$PRINT_VERSION, + 'help' => \$PRINT_HELP); + +GetOptions(\%optctl, "module=s", "source=s", "types:s", "output-dir:s", "inspect-dir:s", "nogtkinit", "type-init-func:s", "verbose", "version", "help"); + +if ($NO_GTK_INIT) { + # Do nothing. This just avoids a warning. + # the option is not used anymore +} + +if ($PRINT_VERSION) { + print "1.5\n"; + exit 0; +} + +if (!$MODULE) { + $PRINT_HELP = 1; +} + +if ($PRINT_HELP) { + print <$MODULE-scan.c") || die "Cannot open $MODULE-scan.c: $!\n"; + +my $old_signals_filename = "$OUTPUT_DIR/$MODULE.signals"; +my $new_signals_filename = "$OUTPUT_DIR/$MODULE.signals.new"; +my $old_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy"; +my $new_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy.new"; +my $old_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces"; +my $new_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces.new"; +my $old_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites"; +my $new_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites.new"; +my $old_args_filename = "$OUTPUT_DIR/$MODULE.args"; +my $new_args_filename = "$OUTPUT_DIR/$MODULE.args.new"; + +my $debug_log="g_message"; +if (!defined($VERBOSE) or $VERBOSE eq "0") { + $debug_log="//$debug_log"; +} + +# write a C program to scan the types + +$includes = ""; +@types = (); +@impl_types = (); + +for () { + if (/^#include/) { + $includes .= $_; + } elsif (/^%/) { + next; + } elsif (/^\s*$/) { + next; + } elsif (/^type:(.*)$/) { + $t = $1; + chomp $t; + push @impl_types, $t; + } else { + chomp; + push @types, $_; + } +} + +$ntypes = @types + @impl_types + 1; + +print OUTPUT < +#include +#include +#include + +#include +EOT + +if ($includes) { + print OUTPUT $includes; +} else { + for (@types) { + print OUTPUT "extern GType $_ (void);\n"; + } +} + +print OUTPUT < +#endif + +static GType *object_types = NULL; + +static GString *xmlstr = NULL; + +static const gchar* +xmlprint (gint indent, const gchar *tag, const gchar *data) +{ + const gchar indent_str[] = " "; + + /* reset */ + g_string_truncate (xmlstr, 0); + g_string_append_len (xmlstr, indent_str, MIN (indent, strlen (indent_str))); + g_string_append_printf (xmlstr, "<%s>", tag); + + if (data) { + gchar *s; + + s = g_markup_escape_text (data, -1); + g_string_append (xmlstr, s); + g_free (s); + } + + g_string_append_printf (xmlstr, "\\n", tag); + return xmlstr->str; +} + +static gint +gst_feature_sort_compare (gconstpointer a, gconstpointer b) +{ + const gchar *name_a = gst_plugin_feature_get_name ((GstPluginFeature *) a); + const gchar *name_b = gst_plugin_feature_get_name ((GstPluginFeature *) b); + return strcmp (name_a, name_b); +} + +static gint +static_pad_template_compare (gconstpointer a, gconstpointer b) +{ + GstStaticPadTemplate *spt_a = (GstStaticPadTemplate *) a; + GstStaticPadTemplate *spt_b = (GstStaticPadTemplate *) b; + + /* we want SINK before SRC (enum is UNKNOWN, SRC, SINK) */ + if (spt_a->direction != spt_b->direction) + return spt_b->direction - spt_a->direction; + + /* we want ALWAYS first, SOMETIMES second, REQUEST last + * (enum is ALWAYS, SOMETIMES, REQUEST) */ + if (spt_a->presence != spt_b->presence) + return spt_a->presence - spt_b->presence; + + return strcmp (spt_a->name_template, spt_b->name_template); +} + +static GType * +get_object_types (void) +{ + gpointer g_object_class; + GList *plugins = NULL; + GList *factories = NULL; + GList *l; + GstElementFactory *factory = NULL; + GType type; + gint i = 0; + gboolean reinspect; + + /* get a list of features from plugins in our source module */ + plugins = gst_registry_get_plugin_list (gst_registry_get ()); + + xmlstr = g_string_new (""); + + reinspect = !g_file_test ("scanobj-build.stamp", G_FILE_TEST_EXISTS); + + while (plugins) { + GList *features; + GstPlugin *plugin; + const gchar *source; + FILE *inspect = NULL; + gchar *inspect_name; + + plugin = (GstPlugin *) (plugins->data); + plugins = g_list_next (plugins); + source = gst_plugin_get_source (plugin); + if (!source || strcmp (source, "$SOURCE") != 0) { + continue; + } + + /* skip static coreelements plugin with pipeline and bin element factory */ + if (gst_plugin_get_filename (plugin) == NULL) + continue; + + $debug_log ("plugin: %s source: %s", gst_plugin_get_name (plugin), source); + + if (reinspect) { + gchar *basename; + + inspect_name = g_strdup_printf ("$INSPECT_DIR" G_DIR_SEPARATOR_S "plugin-%s.xml", + gst_plugin_get_name (plugin)); + inspect = fopen (inspect_name, "w"); + if (inspect == NULL) { + g_error ("Could not open %s for writing: %s\\n", inspect_name, + g_strerror (errno)); + } + g_free (inspect_name); + + basename = g_path_get_basename (gst_plugin_get_filename (plugin)); + + /* output plugin data */ + fputs ("\\n",inspect); + fputs (xmlprint(2, "name", gst_plugin_get_name (plugin)),inspect); + fputs (xmlprint(2, "description", gst_plugin_get_description (plugin)),inspect); + fputs (xmlprint(2, "filename", gst_plugin_get_filename (plugin)),inspect); + fputs (xmlprint(2, "basename", basename),inspect); + fputs (xmlprint(2, "version", gst_plugin_get_version (plugin)),inspect); + fputs (xmlprint(2, "license", gst_plugin_get_license (plugin)),inspect); + fputs (xmlprint(2, "source", gst_plugin_get_source (plugin)),inspect); + fputs (xmlprint(2, "package", gst_plugin_get_package (plugin)),inspect); + fputs (xmlprint(2, "origin", gst_plugin_get_origin (plugin)),inspect); + fputs (" \\n", inspect); + + g_free (basename); + } + + features = + gst_registry_get_feature_list_by_plugin (gst_registry_get (), + gst_plugin_get_name (plugin)); + + /* sort factories by feature->name */ + features = g_list_sort (features, gst_feature_sort_compare); + + while (features) { + GstPluginFeature *feature; + feature = GST_PLUGIN_FEATURE (features->data); + feature = gst_plugin_feature_load (feature); + if (!feature) { + g_warning ("Could not load plugin feature %s", + gst_plugin_feature_get_name (feature)); + } + + if (GST_IS_ELEMENT_FACTORY (feature)) { + const gchar *pad_dir[] = { "unknown","source","sink" }; + const gchar *pad_pres[] = { "always","sometimes","request" }; + GList *pads, *pad; + + $debug_log (" feature: %s", gst_plugin_feature_get_name (feature)); + + factory = GST_ELEMENT_FACTORY (feature); + factories = g_list_prepend (factories, factory); + + if (reinspect) { + /* output element data */ + fputs (" \\n", inspect); + fputs (xmlprint(6, "name", gst_plugin_feature_get_name (feature)),inspect); + fputs (xmlprint(6, "longname", gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_LONGNAME)),inspect); + fputs (xmlprint(6, "class", gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS)),inspect); + fputs (xmlprint(6, "description", gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_DESCRIPTION)),inspect); + fputs (xmlprint(6, "author", gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_AUTHOR)),inspect); + fputs (" \\n", inspect); + + /* output pad-template data */ + pads = g_list_copy ((GList *) gst_element_factory_get_static_pad_templates (factory)); + pads = g_list_sort (pads, static_pad_template_compare); + for (pad = pads; pad != NULL; pad = pad->next) { + GstStaticPadTemplate *pt = pad->data; + + fputs (" \\n", inspect); + fputs (xmlprint(10, "name", pt->name_template),inspect); + fputs (xmlprint(10, "direction", pad_dir[pt->direction]),inspect); + fputs (xmlprint(10, "presence", pad_pres[pt->presence]),inspect); + fputs (xmlprint(10, "details", pt->static_caps.string),inspect); + fputs (" \\n", inspect); + } + g_list_free (pads); + fputs (" \\n \\n", inspect); + } + } + features = g_list_next (features); + } + + if (reinspect) { + fputs (" \\n", inspect); + fclose (inspect); + } + } + + g_string_free (xmlstr, TRUE); + + $debug_log ("number of element factories: %d", g_list_length (factories)); + + /* allocate the object_types array to hold them */ + object_types = g_new0 (GType, g_list_length (factories)+$ntypes+1); + + l = factories; + i = 0; + + /* fill it */ + while (l) { + factory = GST_ELEMENT_FACTORY (l->data); + type = gst_element_factory_get_element_type (factory); + if (type != 0) { + $debug_log ("adding type for factory %s", gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_LONGNAME)); + object_types[i++] = type; + } else { + g_message ("type info for factory %s not found", + gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_LONGNAME)); + } + l = g_list_next (l); + } + +EOT + +# get_type functions: +for (@types) { +print OUTPUT < uppercase with '_' + * GFileMonitor -> file_monitor + * GIOExtensionPoint -> extension_point + * GtkTreeView -> tree_view + * if 2nd char is upper case too + * search for first lower case and go back one char + * else + * search for next upper case + */ + if (!strncmp (object_name, "Gtk", 3)) + object_arg = object_name + 3; + else if (!strncmp (object_name, "Gnome", 5)) + object_arg = object_name + 5; + else + object_arg = object_name; + + object_arg_lower = g_ascii_strdown (object_arg, -1); + sprintf (pos, "*%s\\n", object_arg_lower); + pos += strlen (pos); + if (!strncmp (object_arg_lower, "widget", 6)) + widget_num = 2; + g_free(object_arg_lower); + + /* Convert signal name to use underscores rather than dashes '-'. */ + strncpy (signal_name, query_info.signal_name, 127); + signal_name[127] = '\\0'; + for (i = 0; signal_name[i]; i++) + { + if (signal_name[i] == '-') + signal_name[i] = '_'; + } + + /* Output the signal parameters. */ + for (param = 0; param < query_info.n_params; param++) + { + type_name = get_type_name (query_info.param_types[param] & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer); + + /* Most arguments to the callback are called "arg1", "arg2", etc. + GtkWidgets are called "widget", "widget2", ... + GtkCallbacks are called "callback", "callback2", ... */ + if (!strcmp (type_name, "GtkWidget")) + { + arg_name = "widget"; + arg_num = &widget_num; + } + else if (!strcmp (type_name, "GtkCallback") + || !strcmp (type_name, "GtkCCallback")) + { + arg_name = "callback"; + arg_num = &callback_num; + } + else + { + arg_name = "arg"; + arg_num = ¶m_num; + } + sprintf (pos, "%s ", type_name); + pos += strlen (pos); + + if (!arg_num || *arg_num == 0) + sprintf (pos, "%s%s\\n", is_pointer ? "*" : " ", arg_name); + else + sprintf (pos, "%s%s%i\\n", is_pointer ? "*" : " ", arg_name, + *arg_num); + pos += strlen (pos); + + if (arg_num) + { + if (*arg_num == 0) + *arg_num = 2; + else + *arg_num += 1; + } + } + + pos = flags; + /* We use one-character flags for simplicity. */ + if (query_info.signal_flags & G_SIGNAL_RUN_FIRST) + *pos++ = 'f'; + if (query_info.signal_flags & G_SIGNAL_RUN_LAST) + *pos++ = 'l'; + if (query_info.signal_flags & G_SIGNAL_RUN_CLEANUP) + *pos++ = 'c'; + if (query_info.signal_flags & G_SIGNAL_NO_RECURSE) + *pos++ = 'r'; + if (query_info.signal_flags & G_SIGNAL_DETAILED) + *pos++ = 'd'; + if (query_info.signal_flags & G_SIGNAL_ACTION) + *pos++ = 'a'; + if (query_info.signal_flags & G_SIGNAL_NO_HOOKS) + *pos++ = 'h'; + *pos = 0; + + /* Output the return type and function name. */ + ret_type = get_type_name (query_info.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer); + + fprintf (fp, + "\\n%s::%s\\n%s%s\\n%s\\n%s\\n\\n", + object_name, query_info.signal_name, ret_type, is_pointer ? "*" : "", flags, buffer); +} + + +/* Returns the type name to use for a signal argument or return value, given + the GtkType from the signal info. It also sets is_pointer to TRUE if the + argument needs a '*' since it is a pointer. */ +static const gchar * +get_type_name (GType type, gboolean * is_pointer) +{ + const gchar *type_name; + + *is_pointer = FALSE; + type_name = g_type_name (type); + + switch (type) { + case G_TYPE_NONE: + case G_TYPE_CHAR: + case G_TYPE_UCHAR: + case G_TYPE_BOOLEAN: + case G_TYPE_INT: + case G_TYPE_UINT: + case G_TYPE_LONG: + case G_TYPE_ULONG: + case G_TYPE_FLOAT: + case G_TYPE_DOUBLE: + case G_TYPE_POINTER: + /* These all have normal C type names so they are OK. */ + return type_name; + + case G_TYPE_STRING: + /* A GtkString is really a gchar*. */ + *is_pointer = TRUE; + return "gchar"; + + case G_TYPE_ENUM: + case G_TYPE_FLAGS: + /* We use a gint for both of these. Hopefully a subtype with a decent + name will be registered and used instead, as GTK+ does itself. */ + return "gint"; + + case G_TYPE_BOXED: + /* The boxed type shouldn't be used itself, only subtypes. Though we + return 'gpointer' just in case. */ + return "gpointer"; + + case G_TYPE_PARAM: + /* A GParam is really a GParamSpec*. */ + *is_pointer = TRUE; + return "GParamSpec"; + +#if GLIB_CHECK_VERSION (2, 25, 9) + case G_TYPE_VARIANT: + *is_pointer = TRUE; + return "GVariant"; +#endif + +default: + break; + } + + /* For all GObject subclasses we can use the class name with a "*", + e.g. 'GtkWidget *'. */ + if (g_type_is_a (type, G_TYPE_OBJECT)) + *is_pointer = TRUE; + + /* Also catch non GObject root types */ + if (G_TYPE_IS_CLASSED (type)) + *is_pointer = TRUE; + + /* All boxed subtypes will be pointers as well. */ + /* Exception: GStrv */ + if (g_type_is_a (type, G_TYPE_BOXED) && + !g_type_is_a (type, G_TYPE_STRV)) + *is_pointer = TRUE; + + /* All pointer subtypes will be pointers as well. */ + if (g_type_is_a (type, G_TYPE_POINTER)) + *is_pointer = TRUE; + + /* But enums are not */ + if (g_type_is_a (type, G_TYPE_ENUM) || + g_type_is_a (type, G_TYPE_FLAGS)) + *is_pointer = FALSE; + + return type_name; +} + + +/* This outputs the hierarchy of all objects which have been initialized, + i.e. by calling their XXX_get_type() initialization function. */ +static void +output_object_hierarchy (void) +{ + FILE *fp; + gint i,j; + GType root, type; + GType root_types[$ntypes] = { G_TYPE_INVALID, }; + + fp = fopen (hierarchy_filename, "w"); + if (fp == NULL) + { + g_warning ("Couldn't open output file: %s : %s", hierarchy_filename, g_strerror(errno)); + return; + } + output_hierarchy (fp, G_TYPE_OBJECT, 0); + output_hierarchy (fp, G_TYPE_INTERFACE, 0); + + for (i=0; object_types[i]; i++) { + root = object_types[i]; + while ((type = g_type_parent (root))) { + root = type; + } + if ((root != G_TYPE_OBJECT) && (root != G_TYPE_INTERFACE)) { + for (j=0; root_types[j]; j++) { + if (root == root_types[j]) { + root = G_TYPE_INVALID; break; + } + } + if(root) { + root_types[j] = root; + output_hierarchy (fp, root, 0); + } + } + } + + fclose (fp); +} + +static int +compare_types (const void *a, const void *b) +{ + const char *na = g_type_name (*((GType *)a)); + const char *nb = g_type_name (*((GType *)b)); + + return g_strcmp0 (na, nb); +} + + +/* This is called recursively to output the hierarchy of a object. */ +static void +output_hierarchy (FILE *fp, + GType type, + guint level) +{ + guint i; + GType *children; + guint n_children; + + if (!type) + return; + + for (i = 0; i < level; i++) + fprintf (fp, " "); + fprintf (fp, "%s\\n", g_type_name (type)); + + children = g_type_children (type, &n_children); + qsort (children, n_children, sizeof (GType), compare_types); + + + for (i=0; i < n_children; i++) + output_hierarchy (fp, children[i], level + 1); + + g_free (children); +} + +static void output_object_interfaces (void) +{ + guint i; + FILE *fp; + + fp = fopen (interfaces_filename, "w"); + if (fp == NULL) + { + g_warning ("Couldn't open output file: %s : %s", interfaces_filename, g_strerror(errno)); + return; + } + output_interfaces (fp, G_TYPE_OBJECT); + + for (i = 0; object_types[i]; i++) + { + if (!g_type_parent (object_types[i]) && + (object_types[i] != G_TYPE_OBJECT) && + G_TYPE_IS_INSTANTIATABLE (object_types[i])) + { + output_interfaces (fp, object_types[i]); + } + } + fclose (fp); +} + +static void +output_interfaces (FILE *fp, + GType type) +{ + guint i; + GType *children, *interfaces; + guint n_children, n_interfaces; + + if (!type) + return; + + interfaces = g_type_interfaces (type, &n_interfaces); + + if (n_interfaces > 0) + { + fprintf (fp, "%s", g_type_name (type)); + for (i=0; i < n_interfaces; i++) + fprintf (fp, " %s", g_type_name (interfaces[i])); + fprintf (fp, "\\n"); + } + g_free (interfaces); + + children = g_type_children (type, &n_children); + + for (i=0; i < n_children; i++) + output_interfaces (fp, children[i]); + + g_free (children); +} + +static void output_interface_prerequisites (void) +{ + FILE *fp; + + fp = fopen (prerequisites_filename, "w"); + if (fp == NULL) + { + g_warning ("Couldn't open output file: %s : %s", prerequisites_filename, g_strerror(errno)); + return; + } + output_prerequisites (fp, G_TYPE_INTERFACE); + fclose (fp); +} + +static void +output_prerequisites (FILE *fp, + GType type) +{ +#if GLIB_CHECK_VERSION(2,1,0) + guint i; + GType *children, *prerequisites; + guint n_children, n_prerequisites; + + if (!type) + return; + + prerequisites = g_type_interface_prerequisites (type, &n_prerequisites); + + if (n_prerequisites > 0) + { + fprintf (fp, "%s", g_type_name (type)); + for (i=0; i < n_prerequisites; i++) + fprintf (fp, " %s", g_type_name (prerequisites[i])); + fprintf (fp, "\\n"); + } + g_free (prerequisites); + + children = g_type_children (type, &n_children); + + for (i=0; i < n_children; i++) + output_prerequisites (fp, children[i]); + + g_free (children); +#endif +} + +static void +output_args (void) +{ + FILE *fp; + gint i; + + fp = fopen (args_filename, "w"); + if (fp == NULL) + { + g_warning ("Couldn't open output file: %s : %s", args_filename, g_strerror(errno)); + return; + } + + for (i = 0; object_types[i]; i++) { + output_object_args (fp, object_types[i]); + } + + fclose (fp); +} + +static gint +compare_param_specs (const void *a, const void *b) +{ + GParamSpec *spec_a = *(GParamSpec **)a; + GParamSpec *spec_b = *(GParamSpec **)b; + + return strcmp (g_param_spec_get_name (spec_a), g_param_spec_get_name (spec_b)); +} + +/* Its common to have unsigned properties restricted + * to the signed range. Therefore we make this look + * a bit nicer by spelling out the max constants. + */ + +/* Don't use "==" with floats, it might trigger a gcc warning. */ +#define GTKDOC_COMPARE_FLOAT(x, y) (x <= y && x >= y) + +static gchar* +describe_double_constant (gdouble value) +{ + gchar *desc; + + if (GTKDOC_COMPARE_FLOAT (value, G_MAXDOUBLE)) + desc = g_strdup ("G_MAXDOUBLE"); + else if (GTKDOC_COMPARE_FLOAT (value, G_MINDOUBLE)) + desc = g_strdup ("G_MINDOUBLE"); + else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXDOUBLE)) + desc = g_strdup ("-G_MAXDOUBLE"); + else if (GTKDOC_COMPARE_FLOAT (value, G_MAXFLOAT)) + desc = g_strdup ("G_MAXFLOAT"); + else if (GTKDOC_COMPARE_FLOAT (value, G_MINFLOAT)) + desc = g_strdup ("G_MINFLOAT"); + else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXFLOAT)) + desc = g_strdup ("-G_MAXFLOAT"); + else{ + /* make sure floats are output with a decimal dot irrespective of + * current locale. Use formatd since we want human-readable numbers + * and do not need the exact same bit representation when deserialising */ + desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE); + g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g", value); + } + + return desc; +} + +static gchar* +describe_signed_constant (gsize size, gint64 value) +{ + gchar *desc = NULL; + + switch (size) { + case 8: + if (value == G_MAXINT64) + desc = g_strdup ("G_MAXINT64"); + else if (value == G_MININT64) + desc = g_strdup ("G_MININT64"); + /* fall through */ + case 4: + if (sizeof (int) == 4) { + if (value == G_MAXINT) + desc = g_strdup ("G_MAXINT"); + else if (value == G_MININT) + desc = g_strdup ("G_MININT"); + else if (value == (gint64)G_MAXUINT) + desc = g_strdup ("G_MAXUINT"); + } + if (value == G_MAXLONG) + desc = g_strdup ("G_MAXLONG"); + else if (value == G_MINLONG) + desc = g_strdup ("G_MINLONG"); + else if (value == (gint64)G_MAXULONG) + desc = g_strdup ("G_MAXULONG"); + /* fall through */ + case 2: + if (sizeof (int) == 2) { + if (value == G_MAXINT) + desc = g_strdup ("G_MAXINT"); + else if (value == G_MININT) + desc = g_strdup ("G_MININT"); + else if (value == (gint64)G_MAXUINT) + desc = g_strdup ("G_MAXUINT"); + } + break; + default: + break; + } + if (!desc) + desc = g_strdup_printf ("%" G_GINT64_FORMAT, value); + + return desc; +} + +static gchar* +describe_unsigned_constant (gsize size, guint64 value) +{ + gchar *desc = NULL; + + switch (size) { + case 8: + if (value == G_MAXINT64) + desc = g_strdup ("G_MAXINT64"); + else if (value == G_MAXUINT64) + desc = g_strdup ("G_MAXUINT64"); + /* fall through */ + case 4: + if (sizeof (int) == 4) { + if (value == (guint64)G_MAXINT) + desc = g_strdup ("G_MAXINT"); + else if (value == G_MAXUINT) + desc = g_strdup ("G_MAXUINT"); + } + if (value == (guint64)G_MAXLONG) + desc = g_strdup ("G_MAXLONG"); + else if (value == G_MAXULONG) + desc = g_strdup ("G_MAXULONG"); + /* fall through */ + case 2: + if (sizeof (int) == 2) { + if (value == (guint64)G_MAXINT) + desc = g_strdup ("G_MAXINT"); + else if (value == G_MAXUINT) + desc = g_strdup ("G_MAXUINT"); + } + break; + default: + break; + } + if (!desc) + desc = g_strdup_printf ("%" G_GUINT64_FORMAT, value); + + return desc; +} + +static gchar* +describe_type (GParamSpec *spec) +{ + gchar *desc; + gchar *lower; + gchar *upper; + + if (G_IS_PARAM_SPEC_CHAR (spec)) + { + GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec); + + lower = describe_signed_constant (sizeof(gchar), pspec->minimum); + upper = describe_signed_constant (sizeof(gchar), pspec->maximum); + if (pspec->minimum == G_MININT8 && pspec->maximum == G_MAXINT8) + desc = g_strdup (""); + else if (pspec->minimum == G_MININT8) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXINT8) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_UCHAR (spec)) + { + GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec); + + lower = describe_unsigned_constant (sizeof(guchar), pspec->minimum); + upper = describe_unsigned_constant (sizeof(guchar), pspec->maximum); + if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT8) + desc = g_strdup (""); + else if (pspec->minimum == 0) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXUINT8) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_INT (spec)) + { + GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec); + + lower = describe_signed_constant (sizeof(gint), pspec->minimum); + upper = describe_signed_constant (sizeof(gint), pspec->maximum); + if (pspec->minimum == G_MININT && pspec->maximum == G_MAXINT) + desc = g_strdup (""); + else if (pspec->minimum == G_MININT) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXINT) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_UINT (spec)) + { + GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec); + + lower = describe_unsigned_constant (sizeof(guint), pspec->minimum); + upper = describe_unsigned_constant (sizeof(guint), pspec->maximum); + if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT) + desc = g_strdup (""); + else if (pspec->minimum == 0) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXUINT) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_LONG (spec)) + { + GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec); + + lower = describe_signed_constant (sizeof(glong), pspec->minimum); + upper = describe_signed_constant (sizeof(glong), pspec->maximum); + if (pspec->minimum == G_MINLONG && pspec->maximum == G_MAXLONG) + desc = g_strdup (""); + else if (pspec->minimum == G_MINLONG) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXLONG) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_ULONG (spec)) + { + GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec); + + lower = describe_unsigned_constant (sizeof(gulong), pspec->minimum); + upper = describe_unsigned_constant (sizeof(gulong), pspec->maximum); + if (pspec->minimum == 0 && pspec->maximum == G_MAXULONG) + desc = g_strdup (""); + else if (pspec->minimum == 0) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXULONG) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_INT64 (spec)) + { + GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec); + + lower = describe_signed_constant (sizeof(gint64), pspec->minimum); + upper = describe_signed_constant (sizeof(gint64), pspec->maximum); + if (pspec->minimum == G_MININT64 && pspec->maximum == G_MAXINT64) + desc = g_strdup (""); + else if (pspec->minimum == G_MININT64) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXINT64) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_UINT64 (spec)) + { + GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec); + + lower = describe_unsigned_constant (sizeof(guint64), pspec->minimum); + upper = describe_unsigned_constant (sizeof(guint64), pspec->maximum); + if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT64) + desc = g_strdup (""); + else if (pspec->minimum == 0) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXUINT64) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_FLOAT (spec)) + { + GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec); + + lower = describe_double_constant (pspec->minimum); + upper = describe_double_constant (pspec->maximum); + if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXFLOAT)) + { + if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT)) + desc = g_strdup (""); + else + desc = g_strdup_printf ("<= %s", upper); + } + else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT)) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_DOUBLE (spec)) + { + GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec); + + lower = describe_double_constant (pspec->minimum); + upper = describe_double_constant (pspec->maximum); + if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXDOUBLE)) + { + if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE)) + desc = g_strdup (""); + else + desc = g_strdup_printf ("<= %s", upper); + } + else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE)) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } +#if GLIB_CHECK_VERSION (2, 12, 0) + else if (G_IS_PARAM_SPEC_GTYPE (spec)) + { + GParamSpecGType *pspec = G_PARAM_SPEC_GTYPE (spec); + gboolean is_pointer; + + desc = g_strdup (get_type_name (pspec->is_a_type, &is_pointer)); + } +#endif +#if GLIB_CHECK_VERSION (2, 25, 9) + else if (G_IS_PARAM_SPEC_VARIANT (spec)) + { + GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec); + gchar *variant_type; + + variant_type = g_variant_type_dup_string (pspec->type); + desc = g_strdup_printf ("GVariant<%s>", variant_type); + g_free (variant_type); + } +#endif + else + { + desc = g_strdup (""); + } + + return desc; +} + +static gchar* +describe_default (GParamSpec *spec) +{ + gchar *desc; + + if (G_IS_PARAM_SPEC_CHAR (spec)) + { + GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec); + + desc = g_strdup_printf ("%d", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_UCHAR (spec)) + { + GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec); + + desc = g_strdup_printf ("%u", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_BOOLEAN (spec)) + { + GParamSpecBoolean *pspec = G_PARAM_SPEC_BOOLEAN (spec); + + desc = g_strdup_printf ("%s", pspec->default_value ? "TRUE" : "FALSE"); + } + else if (G_IS_PARAM_SPEC_INT (spec)) + { + GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec); + + desc = g_strdup_printf ("%d", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_UINT (spec)) + { + GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec); + + desc = g_strdup_printf ("%u", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_LONG (spec)) + { + GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec); + + desc = g_strdup_printf ("%ld", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_LONG (spec)) + { + GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec); + + desc = g_strdup_printf ("%lu", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_INT64 (spec)) + { + GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec); + + desc = g_strdup_printf ("%" G_GINT64_FORMAT, pspec->default_value); + } + else if (G_IS_PARAM_SPEC_UINT64 (spec)) + { + GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec); + + desc = g_strdup_printf ("%" G_GUINT64_FORMAT, pspec->default_value); + } + else if (G_IS_PARAM_SPEC_UNICHAR (spec)) + { + GParamSpecUnichar *pspec = G_PARAM_SPEC_UNICHAR (spec); + + if (g_unichar_isprint (pspec->default_value)) + desc = g_strdup_printf ("'%c'", pspec->default_value); + else + desc = g_strdup_printf ("%u", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_ENUM (spec)) + { + GParamSpecEnum *pspec = G_PARAM_SPEC_ENUM (spec); + + GEnumValue *value = g_enum_get_value (pspec->enum_class, pspec->default_value); + if (value) + desc = g_strdup_printf ("%s", value->value_name); + else + desc = g_strdup_printf ("%d", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_FLAGS (spec)) + { + GParamSpecFlags *pspec = G_PARAM_SPEC_FLAGS (spec); + guint default_value; + GString *acc; + + default_value = pspec->default_value; + acc = g_string_new (""); + + while (default_value) + { + GFlagsValue *value = g_flags_get_first_value (pspec->flags_class, default_value); + + if (!value) + break; + + if (acc->len > 0) + g_string_append (acc, "|"); + g_string_append (acc, value->value_name); + + default_value &= ~value->value; + } + + if (default_value == 0) + desc = g_string_free (acc, FALSE); + else + { + desc = g_strdup_printf ("%d", pspec->default_value); + g_string_free (acc, TRUE); + } + } + else if (G_IS_PARAM_SPEC_FLOAT (spec)) + { + GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec); + + /* make sure floats are output with a decimal dot irrespective of + * current locale. Use formatd since we want human-readable numbers + * and do not need the exact same bit representation when deserialising */ + desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE); + g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g", + pspec->default_value); + } + else if (G_IS_PARAM_SPEC_DOUBLE (spec)) + { + GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec); + + /* make sure floats are output with a decimal dot irrespective of + * current locale. Use formatd since we want human-readable numbers + * and do not need the exact same bit representation when deserialising */ + desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE); + g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g", + pspec->default_value); + } + else if (G_IS_PARAM_SPEC_STRING (spec)) + { + GParamSpecString *pspec = G_PARAM_SPEC_STRING (spec); + + if (pspec->default_value) + { + gchar *esc = g_strescape (pspec->default_value, NULL); + + desc = g_strdup_printf ("\\"%s\\"", esc); + + g_free (esc); + } + else + desc = g_strdup_printf ("NULL"); + } + else + { + desc = g_strdup (""); + } + + return desc; +} + + +static void +output_object_args (FILE *fp, GType object_type) +{ + gpointer class; + const gchar *object_class_name; + guint arg; + gchar flags[16], *pos; + GParamSpec **properties; + guint n_properties; + gboolean child_prop; + gboolean style_prop; + gboolean is_pointer; + const gchar *type_name; + gchar *type_desc; + gchar *default_value; + + if (G_TYPE_IS_OBJECT (object_type)) + { + class = g_type_class_peek (object_type); + if (!class) + return; + + properties = g_object_class_list_properties (class, &n_properties); + } +#if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 3) + else if (G_TYPE_IS_INTERFACE (object_type)) + { + class = g_type_default_interface_ref (object_type); + + if (!class) + return; + + properties = g_object_interface_list_properties (class, &n_properties); + } +#endif + else + return; + + object_class_name = g_type_name (object_type); + + child_prop = FALSE; + style_prop = FALSE; + + while (TRUE) { + qsort (properties, n_properties, sizeof (GParamSpec *), compare_param_specs); + for (arg = 0; arg < n_properties; arg++) + { + GParamSpec *spec = properties[arg]; + const gchar *nick, *blurb, *dot; + + if (spec->owner_type != object_type) + continue; + + pos = flags; + /* We use one-character flags for simplicity. */ + if (child_prop && !style_prop) + *pos++ = 'c'; + if (style_prop) + *pos++ = 's'; + if (spec->flags & G_PARAM_READABLE) + *pos++ = 'r'; + if (spec->flags & G_PARAM_WRITABLE) + *pos++ = 'w'; + if (spec->flags & G_PARAM_CONSTRUCT) + *pos++ = 'x'; + if (spec->flags & G_PARAM_CONSTRUCT_ONLY) + *pos++ = 'X'; + *pos = 0; + + nick = g_param_spec_get_nick (spec); + blurb = g_param_spec_get_blurb (spec); + + dot = ""; + if (blurb) { + int str_len = strlen (blurb); + if (str_len > 0 && blurb[str_len - 1] != '.') + dot = "."; + } + + type_desc = describe_type (spec); + default_value = describe_default (spec); + type_name = get_type_name (spec->value_type, &is_pointer); + fprintf (fp, "\\n%s::%s\\n%s%s\\n%s\\n%s\\n%s\\n%s%s\\n%s\\n\\n\\n", + object_class_name, g_param_spec_get_name (spec), type_name, is_pointer ? "*" : "", type_desc, flags, nick ? nick : "(null)", blurb ? blurb : "(null)", dot, default_value); + g_free (type_desc); + g_free (default_value); + } + + g_free (properties); + +#ifdef GTK_IS_CONTAINER_CLASS + if (!child_prop && GTK_IS_CONTAINER_CLASS (class)) { + properties = gtk_container_class_list_child_properties (class, &n_properties); + child_prop = TRUE; + continue; + } +#endif + +#ifdef GTK_IS_CELL_AREA_CLASS + if (!child_prop && GTK_IS_CELL_AREA_CLASS (class)) { + properties = gtk_cell_area_class_list_cell_properties (class, &n_properties); + child_prop = TRUE; + continue; + } +#endif + +#ifdef GTK_IS_WIDGET_CLASS +#if GTK_CHECK_VERSION(2,1,0) + if (!style_prop && GTK_IS_WIDGET_CLASS (class)) { + properties = gtk_widget_class_list_style_properties (GTK_WIDGET_CLASS (class), &n_properties); + style_prop = TRUE; + continue; + } +#endif +#endif + + break; + } +} +EOT + +close OUTPUT; + +# Compile and run our file + +$CC = $ENV{CC} ? $ENV{CC} : "gcc"; +$LD = $ENV{LD} ? $ENV{LD} : $CC; +$CFLAGS = $ENV{CFLAGS} ? "$ENV{CFLAGS}" : ""; +$LDFLAGS = $ENV{LDFLAGS} ? $ENV{LDFLAGS} : ""; + +my $o_file; +if ($CC =~ /libtool/) { + $o_file = "$MODULE-scan.lo" +} else { + $o_file = "$MODULE-scan.o" +} + +my $stdout=""; +if (!defined($VERBOSE) or $VERBOSE eq "0") { + $stdout=">/dev/null"; +} + +# Compiling scanner +$command = "$CC $stdout $CFLAGS -c -o $o_file $MODULE-scan.c"; +system("($command)") == 0 or die "Compilation of scanner failed: $!\n"; + +# Linking scanner +$command = "$LD $stdout -o $MODULE-scan $o_file $LDFLAGS"; +system($command) == 0 or die "Linking of scanner failed: $!\n"; + +# Running scanner $MODULE-scan "; +system("sh -c ./$MODULE-scan") == 0 or die "Scan failed: $!\n"; + +if (!defined($ENV{"GTK_DOC_KEEP_INTERMEDIATE"})) { + unlink "./$MODULE-scan.c", "./$MODULE-scan.o", "./$MODULE-scan.lo", "./$MODULE-scan"; +} + +&UpdateFileIfChanged ($old_hierarchy_filename, $new_hierarchy_filename, 0); +# we will merge these in scangobj-merge.py +#&UpdateFileIfChanged ($old_interfaces_filename, $new_interfaces_filename, 0); +#&UpdateFileIfChanged ($old_prerequisites_filename, $new_prerequisites_filename, 0); +#&UpdateFileIfChanged ($old_signals_filename, $new_signals_filename, 0); +#&UpdateFileIfChanged ($old_args_filename, $new_args_filename, 0); + diff --git a/common/gtk-doc-plugins.mak b/common/gtk-doc-plugins.mak new file mode 100644 index 0000000..f19e7d7 --- /dev/null +++ b/common/gtk-doc-plugins.mak @@ -0,0 +1,382 @@ +# This is an include file specifically tuned for building documentation +# for GStreamer plug-ins + +help: + @echo + @echo "If you are a doc maintainer, run 'make update' to update" + @echo "the documentation files maintained in git" + @echo + @echo Other useful make targets: + @echo + @echo check-inspected-versions: make sure the inspected plugin info + @echo is up to date before a release + @echo + +# update the stuff maintained by doc maintainers +update: scanobj-update + $(MAKE) check-outdated-docs + +# We set GPATH here; this gives us semantics for GNU make +# which are more like other make's VPATH, when it comes to +# whether a source that is a target of one rule is then +# searched for in VPATH/GPATH. +# +GPATH = $(srcdir) + +# thomas: make docs parallel installable +TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE)-@GST_API_VERSION@ + +MAINTAINER_DOC_STAMPS = \ + scanobj-build.stamp + +EXTRA_DIST = \ + $(MAINTAINER_DOC_STAMPS) \ + $(srcdir)/inspect/*.xml \ + $(SCANOBJ_FILES) \ + $(content_files) \ + $(extra_files) \ + $(HTML_IMAGES) \ + $(DOC_MAIN_SGML_FILE) \ + $(DOC_OVERRIDES) \ + $(DOC_MODULE)-sections.txt + +# we don't add scanobj-build.stamp here since they are built manually by docs +# maintainers and result is commited to git +DOC_STAMPS = \ + scan-build.stamp \ + tmpl-build.stamp \ + sgml-build.stamp \ + html-build.stamp \ + scan.stamp \ + tmpl.stamp \ + sgml.stamp \ + html.stamp + +# files generated/updated by gtkdoc-scangobj +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals \ + $(DOC_MODULE).types + +SCANOBJ_FILES_O = \ + .libs/$(DOC_MODULE)-scan.o + +# files generated/updated by gtkdoc-scan +SCAN_FILES = \ + $(DOC_MODULE)-sections.txt \ + $(DOC_MODULE)-overrides.txt \ + $(DOC_MODULE)-decl.txt \ + $(DOC_MODULE)-decl-list.txt + + +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +CLEANFILES = \ + $(SCANOBJ_FILES_O) \ + $(REPORT_FILES) \ + $(DOC_STAMPS) \ + inspect-registry.xml + +INSPECT_DIR = inspect + +if ENABLE_GTK_DOC +all-local: html-build.stamp + +### inspect GStreamer plug-ins; done by documentation maintainer ### + +# only look at the plugins in this module when building inspect .xml stuff +INSPECT_REGISTRY=$(top_builddir)/docs/plugins/inspect-registry.xml +INSPECT_ENVIRONMENT=\ + LC_ALL=C \ + GST_PLUGIN_SYSTEM_PATH_1_0= \ + GST_PLUGIN_PATH_1_0=$(top_builddir)/gst:$(top_builddir)/sys:$(top_builddir)/ext:$(top_builddir)/plugins:$(top_builddir)/src:$(top_builddir)/gnl \ + GST_REGISTRY_1_0=$(INSPECT_REGISTRY) \ + PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INSPECT_EXTRA_ENVIRONMENT) + +#### scan gobjects; done by documentation maintainer #### +scanobj-update: + -rm scanobj-build.stamp + $(MAKE) scanobj-build.stamp + +# gstdoc-scanobj produces 5 output files (.new) +# scangobj-merge.py merges them into the file which we commit later +# TODO: also merge the hierarchy +scanobj-build.stamp: $(SCANOBJ_DEPS) $(basefiles) + @echo " DOC Introspecting gobjects" + @if test x"$(srcdir)" != x. ; then \ + for f in $(SCANOBJ_FILES) $(SCAN_FILES); \ + do \ + if test -e $(srcdir)/$$f; then cp -u $(srcdir)/$$f . ; fi; \ + done; \ + fi; \ + mkdir -p $(INSPECT_DIR); \ + scanobj_options=""; \ + if test "x$(V)" = "x1"; then \ + scanobj_options="--verbose"; \ + fi; \ + $(INSPECT_ENVIRONMENT) \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" \ + CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS) $(WARNING_CFLAGS)" \ + LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ + $(GST_DOC_SCANOBJ) $$scanobj_options --type-init-func="gst_init(NULL,NULL)" \ + --module=$(DOC_MODULE) --source=$(PACKAGE) --inspect-dir=$(INSPECT_DIR) && \ + echo " DOC Merging introspection data" && \ + $(PYTHON) \ + $(top_srcdir)/common/scangobj-merge.py $(DOC_MODULE) || exit 1; \ + if test x"$(srcdir)" != x. ; then \ + for f in $(SCANOBJ_FILES); \ + do \ + cmp -s ./$$f $(srcdir)/$$f || cp ./$$f $(srcdir)/ ; \ + done; \ + fi; \ + touch scanobj-build.stamp + +$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(SCANOBJ_FILES_O): scan-build.stamp + @true + +### scan headers; done on every build ### +scan-build.stamp: $(HFILE_GLOB) $(EXTRA_HFILES) $(basefiles) scanobj-build.stamp + @echo ' DOC Scanning header files' + @if test x"$(srcdir)" != x. ; then \ + for f in $(SCANOBJ_FILES) $(SCAN_FILES); \ + do \ + if test -e $(srcdir)/$$f; then cp -u $(srcdir)/$$f . ; fi; \ + done; \ + fi + @_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-scan \ + $(SCAN_OPTIONS) $(EXTRA_HFILES) \ + --module=$(DOC_MODULE) \ + $${_source_dir} \ + --ignore-headers="$(IGNORE_HFILES)"; \ + touch scan-build.stamp + +#### update templates; done on every build #### + +# in a non-srcdir build, we need to copy files from the previous step +# and the files from previous runs of this step +tmpl-build.stamp: $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_OVERRIDES) + @echo ' DOC Rebuilding template files' + @if test x"$(srcdir)" != x. ; then \ + for f in $(SCANOBJ_FILES) $(SCAN_FILES); \ + do \ + if test -e $(srcdir)/$$f; then cp -u $(srcdir)/$$f . ; fi; \ + done; \ + fi + @gtkdoc-mktmpl --module=$(DOC_MODULE) + @$(PYTHON) \ + $(top_srcdir)/common/mangle-tmpl.py $(srcdir)/$(INSPECT_DIR) tmpl + @touch tmpl-build.stamp + +tmpl.stamp: tmpl-build.stamp + @true + +#### xml #### + +sgml-build.stamp: tmpl.stamp scan-build.stamp $(CFILE_GLOB) $(top_srcdir)/common/plugins.xsl $(expand_content_files) + @echo ' DOC Building XML' + @-mkdir -p xml + @for a in $(srcdir)/$(INSPECT_DIR)/*.xml; do \ + xsltproc --stringparam module $(MODULE) \ + $(top_srcdir)/common/plugins.xsl $$a > xml/`basename $$a`; done + @for f in $(EXAMPLE_CFILES); do \ + $(PYTHON) $(top_srcdir)/common/c-to-xml.py $$f > xml/element-`basename $$f .c`.xml; done + @gtkdoc-mkdb \ + --module=$(DOC_MODULE) \ + --source-dir=$(DOC_SOURCE_DIR) \ + --expand-content-files="$(expand_content_files)" \ + --main-sgml-file=$(srcdir)/$(DOC_MAIN_SGML_FILE) \ + --output-format=xml \ + --ignore-files="$(IGNORE_HFILES) $(IGNORE_CFILES)" \ + $(MKDB_OPTIONS) + @cp ../version.entities xml + @touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +#### html #### + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) + @echo ' DOC Building HTML' + @rm -rf html + @mkdir html + @cp $(srcdir)/$(DOC_MAIN_SGML_FILE) html + @for f in $(content_files); do cp $(srcdir)/$$f html; done + @cp -pr xml html + @cp ../version.entities html + @mkhtml_options=""; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$(?)" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkhtml_options="$$mkhtml_options --verbose"; \ + fi; \ + fi; \ + cd html && gtkdoc-mkhtml $$mkhtml_options $(DOC_MODULE)-@GST_API_VERSION@ $(DOC_MAIN_SGML_FILE) + @rm -f html/$(DOC_MAIN_SGML_FILE) + @rm -rf html/xml + @rm -f html/version.entities + @test "x$(HTML_IMAGES)" = "x" || for i in "" $(HTML_IMAGES) ; do \ + if test "$$i" != ""; then cp $(srcdir)/$$i html ; fi; done + @echo ' DOC Fixing cross-references' + @gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) + @touch html-build.stamp + +clean-local-gtkdoc: + @rm -rf xml tmpl html +# clean files copied for nonsrcdir templates build + @if test x"$(srcdir)" != x. ; then \ + rm -rf $(SCANOBJ_FILES) $(SCAN_FILES) $(REPORT_FILES) \ + $(MAINTAINER_DOC_STAMPS); \ + fi +else +all-local: +clean-local-gtkdoc: +endif + +clean-local: clean-local-gtkdoc + @rm -f *~ *.bak + @rm -rf .libs + +distclean-local: + @rm -f $(REPORT_FILES) \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + @rm -rf tmpl/*.sgml.bak + @rm -f $(DOC_MODULE).hierarchy + @rm -f *.stamp || true + @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + rm -f $(DOC_MODULE)-docs.sgml ; \ + rm -f $(DOC_MODULE).types ; \ + rm -f $(DOC_MODULE).interfaces ; \ + rm -f $(DOC_MODULE)-overrides.txt ; \ + rm -f $(DOC_MODULE).prerequisites ; \ + rm -f $(DOC_MODULE)-sections.txt ; \ + rm -rf tmpl/*.sgml ; \ + rm -rf $(INSPECT_DIR); \ + fi + @rm -rf *.o + +MAINTAINERCLEANFILES = $(MAINTAINER_DOC_STAMPS) + +# thomas: make docs parallel installable; devhelp requires majorminor too +install-data-local: + (installfiles=`echo $(builddir)/html/*.sgml $(builddir)/html/*.html $(builddir)/html/*.png $(builddir)/html/*.css`; \ + if test "$$installfiles" = '$(builddir)/html/*.sgml $(builddir)/html/*.html $(builddir)/html/*.png $(builddir)/html/*.css'; \ + then echo '-- Nothing to install' ; \ + else \ + $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR); \ + for i in $$installfiles; do \ + echo '-- Installing '$$i ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \ + done; \ + pngfiles=`echo ./html/*.png`; \ + if test "$$pngfiles" != './html/*.png'; then \ + for i in $$pngfiles; do \ + echo '-- Installing '$$i ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \ + done; \ + fi; \ + echo '-- Installing $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2' ; \ + if test -e $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; then \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2 \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; \ + fi; \ + $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$(DESTDIR)$(TARGET_DIR) || true ; \ + fi) +uninstall-local: + if test -d $(DESTDIR)$(TARGET_DIR); then \ + rm -rf $(DESTDIR)$(TARGET_DIR)/*; \ + rmdir -p $(DESTDIR)$(TARGET_DIR) 2>/dev/null || true; \ + else \ + echo '-- Nothing to uninstall' ; \ + fi; + +# +# Checks +# +if ENABLE_GTK_DOC +check-hierarchy: $(DOC_MODULE).hierarchy + @if grep ' ' $(DOC_MODULE).hierarchy; then \ + echo "$(DOC_MODULE).hierarchy contains tabs, please fix"; \ + /bin/false; \ + fi + +check: check-hierarchy +endif + +# wildcard is apparently not portable to other makes, hence the use of find +inspect_files = $(shell find $(srcdir)/$(INSPECT_DIR) -name '*.xml') + +check-inspected-versions: + @echo Checking plugin versions of inspected plugin data ...; \ + fail=0 ; \ + for each in $(inspect_files) ; do \ + if (grep -H '' $$each | grep -v '$(VERSION)'); then \ + echo $$each should be fixed to say version $(VERSION) or be removed ; \ + echo "sed -i -e 's//$(VERSION)<\/version>/'" $$each; \ + echo ; \ + fail=1; \ + fi ; \ + done ; \ + exit $$fail + +check-outdated-docs: + $(AM_V_GEN)echo Checking for outdated plugin inspect data ...; \ + fail=0 ; \ + if [ -d $(top_srcdir)/.git/ ]; then \ + files=`find $(srcdir)/inspect/ -name '*xml'`; \ + for f in $$files; do \ + ver=`grep '$(PACKAGE_VERSION)' $$f`; \ + if test "x$$ver" = "x"; then \ + plugin=`echo $$f | sed -e 's/^.*plugin-//' -e 's/.xml//'`; \ + # echo "Checking $$plugin $$f"; \ + pushd "$(top_srcdir)" >/dev/null; \ + pinit=`git grep -A3 GST_PLUGIN_DEFINE -- ext/ gst/ sys/ | grep "\"$$plugin\""`; \ + popd >/dev/null; \ + # echo "[$$pinit]"; \ + if test "x$$pinit" = "x"; then \ + printf " **** outdated docs for plugin %-15s: %s\n" $$plugin $$f; \ + fail=1; \ + fi; \ + fi; \ + done; \ + fi ; \ + exit $$fail + +# +# Require gtk-doc when making dist +# +if ENABLE_GTK_DOC +dist-check-gtkdoc: +else +dist-check-gtkdoc: + @echo "*** gtk-doc must be installed and enabled in order to make dist" + @false +endif + +# FIXME: decide whether we want to dist generated html or not +# also this only works, if the project has been build before +# we could dist html only if its there, but that might lead to missing html in +# tarballs +dist-hook: dist-check-gtkdoc dist-hook-local + mkdir $(distdir)/html + cp html/* $(distdir)/html + -cp $(srcdir)/$(DOC_MODULE).types $(distdir)/ + -cp $(srcdir)/$(DOC_MODULE)-sections.txt $(distdir)/ + cd $(distdir) && rm -f $(DISTCLEANFILES) + -gtkdoc-rebase --online --relative --html-dir=$(distdir)/html + +.PHONY : dist-hook-local docs check-outdated-docs inspect + +# avoid spurious build errors when distchecking with -jN +.NOTPARALLEL: diff --git a/common/gtk-doc.mak b/common/gtk-doc.mak new file mode 100644 index 0000000..9d76889 --- /dev/null +++ b/common/gtk-doc.mak @@ -0,0 +1,227 @@ +########################################################################### +# Everything below here is generic and you shouldn't need to change it. +########################################################################### +# thomas: except of course that we did + +# thomas: copied from glib-2 +# We set GPATH here; this gives us semantics for GNU make +# which are more like other make's VPATH, when it comes to +# whether a source that is a target of one rule is then +# searched for in VPATH/GPATH. +# +GPATH = $(srcdir) + +# thomas: make docs parallel installable +TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE)-@GST_API_VERSION@ + +EXTRA_DIST = \ + $(content_files) \ + $(extra_files) \ + $(HTML_IMAGES) \ + $(DOC_MAIN_SGML_FILE) \ + $(DOC_MODULE).types \ + $(DOC_OVERRIDES) \ + $(DOC_MODULE)-sections.txt + +DOC_STAMPS = \ + setup-build.stamp \ + scan-build.stamp \ + sgml-build.stamp \ + html-build.stamp \ + sgml.stamp \ + html.stamp + +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals \ + .libs/$(DOC_MODULE)-scan.o + +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) doc-registry.xml + +if ENABLE_GTK_DOC +all-local: html-build.stamp + +#### setup #### + +setup-build.stamp: $(content_files) + -@if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + echo ' DOC Preparing build'; \ + files=`echo $(DOC_MAIN_SGML_FILE) $(DOC_OVERRIDES) $(DOC_MODULE)-sections.txt $(DOC_MODULE).types $(content_files)`; \ + if test "x$$files" != "x" ; then \ + for file in $$files ; do \ + test -f $(abs_srcdir)/$$file && \ + cp -pu $(abs_srcdir)/$$file $(abs_builddir)/ || true; \ + done; \ + fi; \ + fi + @touch setup-build.stamp + +#### scan #### + +# in the case of non-srcdir builds, the built gst directory gets added +# to gtk-doc scanning; but only then, to avoid duplicates +scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB) + @echo ' DOC Scanning header files' + @_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-scan \ + $(SCAN_OPTIONS) $(EXTRA_HFILES) \ + --module=$(DOC_MODULE) \ + $${_source_dir} \ + --ignore-headers="$(IGNORE_HFILES)" + @if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null; then \ + echo " DOC Introspecting gobjects"; \ + GST_PLUGIN_SYSTEM_PATH_1_0=`cd $(top_builddir) && pwd` \ + GST_PLUGIN_PATH_1_0= \ + GST_REGISTRY_1_0=doc-registry.xml \ + $(GTKDOC_EXTRA_ENVIRONMENT) \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" \ + CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" \ + LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ + gtkdoc-scangobj --type-init-func="gst_init(NULL,NULL)" \ + --module=$(DOC_MODULE) ; \ + else \ + for i in $(SCANOBJ_FILES) ; do \ + test -f $$i || touch $$i ; \ + done \ + fi + @touch scan-build.stamp + +$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp + @true + +#### xml #### + +sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(expand_content_files) + @echo ' DOC Building XML' + @gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) --output-format=xml $(MKDB_OPTIONS) + @cp ../version.entities xml + @touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +#### html #### + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) + @echo ' DOC Building HTML' + @rm -rf html + @mkdir html + @cp -pr xml html + @cp ../version.entities ./ + @mkhtml_options=""; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$(?)" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkhtml_options="$$mkhtml_options --verbose"; \ + fi; \ + fi; \ + @gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ + if test "$(?)" = "0"; then \ + mkhtml_options=--path="$(abs_srcdir)"; \ + fi; \ + cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE)-@GST_API_VERSION@ ../$(DOC_MAIN_SGML_FILE) + @rm -rf html/xml + @rm -f version.entities + @test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) $(abs_builddir)/html ) + @echo ' DOC Fixing cross-references' + @gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) + @touch html-build.stamp + +clean-local-gtkdoc: + @rm -rf xml tmpl html +# clean files copied for nonsrcdir templates build + @if test x"$(srcdir)" != x. ; then \ + rm -rf $(DOC_MODULE).types; \ + fi +else +all-local: +clean-local-gtkdoc: +endif + +clean-local: clean-local-gtkdoc + @rm -f *~ *.bak + @rm -rf .libs + +distclean-local: + @rm -f $(REPORT_FILES) \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + @rm -rf tmpl/*.sgml.bak + @rm -f $(DOC_MODULE).hierarchy + @rm -f *.stamp || true + @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + rm -f $(DOC_MAIN_SGML_FILE) ; \ + rm -f $(DOC_OVERRIDES) ; \ + rm -f $(DOC_MODULE).types ; \ + rm -f $(DOC_MODULE).interfaces ; \ + rm -f $(DOC_MODULE).prerequisites ; \ + rm -f $(DOC_MODULE)-sections.txt ; \ + rm -f $(content_files) ; \ + rm -rf tmpl/*.sgml ; \ + fi + @rm -rf *.o + +maintainer-clean-local: clean + @cd $(srcdir) && rm -rf html \ + xml $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + +# thomas: make docs parallel installable; devhelp requires majorminor too +install-data-local: + (installfiles=`echo $(builddir)/html/*.sgml $(builddir)/html/*.html $(builddir)/html/*.png $(builddir)/html/*.css`; \ + if test "$$installfiles" = '$(builddir)/html/*.sgml $(builddir)/html/*.html $(builddir)/html/*.png $(builddir)/html/*.css'; \ + then echo '-- Nothing to install' ; \ + else \ + $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR); \ + for i in $$installfiles; do \ + echo '-- Installing '$$i ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \ + done; \ + echo '-- Installing $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2' ; \ + if test -e $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; then \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2 \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; \ + fi; \ + $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$(DESTDIR)$(TARGET_DIR) || true ; \ + fi) +uninstall-local: + if test -d $(DESTDIR)$(TARGET_DIR); then \ + rm -rf $(DESTDIR)$(TARGET_DIR)/*; \ + rmdir -p $(DESTDIR)$(TARGET_DIR) 2>/dev/null || true; \ + else \ + echo '-- Nothing to uninstall' ; \ + fi; + + +# +# Require gtk-doc when making dist +# +if ENABLE_GTK_DOC +dist-check-gtkdoc: +else +dist-check-gtkdoc: + @echo "*** gtk-doc must be installed and enabled in order to make dist" + @false +endif + +dist-hook: dist-check-gtkdoc dist-hook-local + mkdir $(distdir)/html + cp html/* $(distdir)/html + -cp $(srcdir)/$(DOC_MODULE).types $(distdir)/ + -cp $(srcdir)/$(DOC_MODULE)-sections.txt $(distdir)/ + cd $(distdir) && rm -f $(DISTCLEANFILES) + -gtkdoc-rebase --online --relative --html-dir=$(distdir)/html + +.PHONY : dist-hook-local docs + +# avoid spurious build errors when distchecking with -jN +.NOTPARALLEL: diff --git a/common/m4/Makefile.am b/common/m4/Makefile.am new file mode 100644 index 0000000..3d387ee --- /dev/null +++ b/common/m4/Makefile.am @@ -0,0 +1,40 @@ +EXTRA_DIST = \ + README \ + as-ac-expand.m4 \ + as-auto-alt.m4 \ + as-compiler-flag.m4 \ + as-compiler.m4 \ + as-docbook.m4 \ + as-gcc-inline-assembly.m4 \ + as-libtool.m4 \ + as-libtool-tags.m4 \ + as-python.m4 \ + as-version.m4 \ + ax_create_stdint_h.m4 \ + glib-gettext.m4 \ + gst-arch.m4 \ + gst-args.m4 \ + gst-check.m4 \ + gst-debuginfo.m4 \ + gst-default.m4 \ + gst-doc.m4 \ + gst-dowhile.m4 \ + gst-error.m4 \ + gst-feature.m4 \ + gst-function.m4 \ + gst-gettext.m4 \ + gst-glib2.m4 \ + gst-libxml2.m4 \ + gst-parser.m4 \ + gst-package-release-datetime.m4 \ + gst-platform.m4 \ + gst-plugindir.m4 \ + gst-plugin-docs.m4 \ + gst-valgrind.m4 \ + gst-x11.m4 \ + gst.m4 \ + gtk-doc.m4 \ + introspection.m4 \ + pkg.m4 \ + check.m4 \ + orc.m4 diff --git a/common/m4/Makefile.in b/common/m4/Makefile.in new file mode 100644 index 0000000..80550ab --- /dev/null +++ b/common/m4/Makefile.in @@ -0,0 +1,594 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = common/m4 +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am README +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-docbook.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-default.m4 \ + $(top_srcdir)/common/m4/gst-doc.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAT_ENTRY_END = @CAT_ENTRY_END@ +CAT_ENTRY_START = @CAT_ENTRY_START@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@ +DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@ +DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@ +DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@ +DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ = @GLIB_REQ@ +GREP = @GREP@ +GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@ +GSTPD_PLUGINS_DIR = @GSTPD_PLUGINS_DIR@ +GSTPG_PLUGINS_DIR = @GSTPG_PLUGINS_DIR@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_BASE_CFLAGS = @GST_BASE_CFLAGS@ +GST_BASE_LIBS = @GST_BASE_LIBS@ +GST_CFLAGS = @GST_CFLAGS@ +GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@ +GST_CHECK_LIBS = @GST_CHECK_LIBS@ +GST_CURRENT = @GST_CURRENT@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBS = @GST_LIBS@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGINS_BAD_CFLAGS = @GST_PLUGINS_BAD_CFLAGS@ +GST_PLUGINS_BAD_DIR = @GST_PLUGINS_BAD_DIR@ +GST_PLUGINS_BAD_LIBS = @GST_PLUGINS_BAD_LIBS@ +GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@ +GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@ +GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@ +GST_PLUGINS_DIR = @GST_PLUGINS_DIR@ +GST_PLUGINS_GOOD_CFLAGS = @GST_PLUGINS_GOOD_CFLAGS@ +GST_PLUGINS_GOOD_DIR = @GST_PLUGINS_GOOD_DIR@ +GST_PLUGINS_GOOD_LIBS = @GST_PLUGINS_GOOD_LIBS@ +GST_REVISION = @GST_REVISION@ +GST_TOOLS_DIR = @GST_TOOLS_DIR@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ +HAVE_DVIPS = @HAVE_DVIPS@ +HAVE_EPSTOPDF = @HAVE_EPSTOPDF@ +HAVE_JADETEX = @HAVE_JADETEX@ +HAVE_PNGTOPNM = @HAVE_PNGTOPNM@ +HAVE_PNMTOPS = @HAVE_PNMTOPS@ +HAVE_PS2PDF = @HAVE_PS2PDF@ +HAVE_XMLLINT = @HAVE_XMLLINT@ +HAVE_XSLTPROC = @HAVE_XSLTPROC@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCGROUP_CFLAGS = @LIBCGROUP_CFLAGS@ +LIBCGROUP_LIBS = @LIBCGROUP_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +XML_CATALOG = @XML_CATALOG@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + README \ + as-ac-expand.m4 \ + as-auto-alt.m4 \ + as-compiler-flag.m4 \ + as-compiler.m4 \ + as-docbook.m4 \ + as-gcc-inline-assembly.m4 \ + as-libtool.m4 \ + as-libtool-tags.m4 \ + as-python.m4 \ + as-version.m4 \ + ax_create_stdint_h.m4 \ + glib-gettext.m4 \ + gst-arch.m4 \ + gst-args.m4 \ + gst-check.m4 \ + gst-debuginfo.m4 \ + gst-default.m4 \ + gst-doc.m4 \ + gst-dowhile.m4 \ + gst-error.m4 \ + gst-feature.m4 \ + gst-function.m4 \ + gst-gettext.m4 \ + gst-glib2.m4 \ + gst-libxml2.m4 \ + gst-parser.m4 \ + gst-package-release-datetime.m4 \ + gst-platform.m4 \ + gst-plugindir.m4 \ + gst-plugin-docs.m4 \ + gst-valgrind.m4 \ + gst-x11.m4 \ + gst.m4 \ + gtk-doc.m4 \ + introspection.m4 \ + pkg.m4 \ + check.m4 \ + orc.m4 + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu common/m4/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu common/m4/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/common/m4/README b/common/m4/README new file mode 100644 index 0000000..867a344 --- /dev/null +++ b/common/m4/README @@ -0,0 +1,3 @@ +All aclocal .m4 files we need are put here and cat'd to acinclude.m4 in +the source root. Official ones (taken from the relevant devel packages) +are named as-is, unofficial ones (or changed ones) get a gst-prefix. diff --git a/common/m4/as-ac-expand.m4 b/common/m4/as-ac-expand.m4 new file mode 100644 index 0000000..d6c9e33 --- /dev/null +++ b/common/m4/as-ac-expand.m4 @@ -0,0 +1,43 @@ +dnl as-ac-expand.m4 0.2.0 +dnl autostars m4 macro for expanding directories using configure's prefix +dnl thomas@apestaart.org + +dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) +dnl example +dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) +dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local + +AC_DEFUN([AS_AC_EXPAND], +[ + EXP_VAR=[$1] + FROM_VAR=[$2] + + dnl first expand prefix and exec_prefix if necessary + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + dnl if no prefix given, then use /usr/local, the default prefix + if test "x$prefix" = "xNONE"; then + prefix="$ac_default_prefix" + fi + dnl if no exec_prefix given, then use prefix + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + dnl loop until it doesn't change anymore + while true; do + new_full_var="`eval echo $full_var`" + if test "x$new_full_var" = "x$full_var"; then break; fi + full_var=$new_full_var + done + + dnl clean up + full_var=$new_full_var + AC_SUBST([$1], "$full_var") + + dnl restore prefix and exec_prefix + prefix=$prefix_save + exec_prefix=$exec_prefix_save +]) diff --git a/common/m4/as-auto-alt.m4 b/common/m4/as-auto-alt.m4 new file mode 100644 index 0000000..3f7920d --- /dev/null +++ b/common/m4/as-auto-alt.m4 @@ -0,0 +1,50 @@ +dnl as-auto-alt.m4 0.0.2 +dnl autostars m4 macro for supplying alternate autotools versions to configure +dnl thomas@apestaart.org +dnl +dnl AS_AUTOTOOLS_ALTERNATE() +dnl +dnl supplies --with arguments for autoconf, autoheader, automake, aclocal + +AC_DEFUN([AS_AUTOTOOLS_ALTERNATE], +[ + dnl allow for different autoconf version + AC_ARG_WITH(autoconf, + AC_HELP_STRING([--with-autoconf], + [use a different autoconf for regeneration of Makefiles]), + [ + unset AUTOCONF + AM_MISSING_PROG(AUTOCONF, ${withval}) + AC_MSG_NOTICE([Using $AUTOCONF as autoconf]) + ]) + + dnl allow for different autoheader version + AC_ARG_WITH(autoheader, + AC_HELP_STRING([--with-autoheader], + [use a different autoheader for regeneration of Makefiles]), + [ + unset AUTOHEADER + AM_MISSING_PROG(AUTOHEADER, ${withval}) + AC_MSG_NOTICE([Using $AUTOHEADER as autoheader]) + ]) + + dnl allow for different automake version + AC_ARG_WITH(automake, + AC_HELP_STRING([--with-automake], + [use a different automake for regeneration of Makefiles]), + [ + unset AUTOMAKE + AM_MISSING_PROG(AUTOMAKE, ${withval}) + AC_MSG_NOTICE([Using $AUTOMAKE as automake]) + ]) + + dnl allow for different aclocal version + AC_ARG_WITH(aclocal, + AC_HELP_STRING([--with-aclocal], + [use a different aclocal for regeneration of Makefiles]), + [ + unset ACLOCAL + AM_MISSING_PROG(ACLOCAL, ${withval}) + AC_MSG_NOTICE([Using $ACLOCAL as aclocal]) + ]) +]) diff --git a/common/m4/as-compiler-flag.m4 b/common/m4/as-compiler-flag.m4 new file mode 100644 index 0000000..8bb853a --- /dev/null +++ b/common/m4/as-compiler-flag.m4 @@ -0,0 +1,96 @@ +dnl as-compiler-flag.m4 0.1.0 + +dnl autostars m4 macro for detection of compiler flags + +dnl David Schleef +dnl Tim-Philipp Müller + +dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) +dnl Tries to compile with the given CFLAGS. +dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, +dnl and ACTION-IF-NOT-ACCEPTED otherwise. + +AC_DEFUN([AS_COMPILER_FLAG], +[ + AC_MSG_CHECKING([to see if compiler understands $1]) + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $1" + + AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + $2 + true + else + $3 + true + fi + AC_MSG_RESULT([$flag_ok]) +]) + +dnl AS_CXX_COMPILER_FLAG(CPPFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) +dnl Tries to compile with the given CPPFLAGS. +dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, +dnl and ACTION-IF-NOT-ACCEPTED otherwise. + +AC_DEFUN([AS_CXX_COMPILER_FLAG], +[ + AC_REQUIRE([AC_PROG_CXX]) + + AC_MSG_CHECKING([to see if c++ compiler understands $1]) + + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $1" + + AC_LANG_PUSH(C++) + + AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) + CPPFLAGS="$save_CPPFLAGS" + + if test "X$flag_ok" = Xyes ; then + $2 + true + else + $3 + true + fi + + AC_LANG_POP(C++) + + AC_MSG_RESULT([$flag_ok]) +]) + +dnl AS_OBJC_COMPILER_FLAG(CPPFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) +dnl Tries to compile with the given CPPFLAGS. +dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, +dnl and ACTION-IF-NOT-ACCEPTED otherwise. + +AC_DEFUN([AS_OBJC_COMPILER_FLAG], +[ + AC_REQUIRE([AC_PROG_OBJC]) + + AC_MSG_CHECKING([to see if Objective C compiler understands $1]) + + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $1" + + AC_LANG_PUSH([Objective C]) + + AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) + CPPFLAGS="$save_CPPFLAGS" + + if test "X$flag_ok" = Xyes ; then + $2 + true + else + $3 + true + fi + + AC_LANG_POP([Objective C]) + + AC_MSG_RESULT([$flag_ok]) +]) + diff --git a/common/m4/as-compiler.m4 b/common/m4/as-compiler.m4 new file mode 100644 index 0000000..309a060 --- /dev/null +++ b/common/m4/as-compiler.m4 @@ -0,0 +1,44 @@ +dnl as-compiler.m4 0.1.0 + +dnl autostars m4 macro for detection of compiler flavor + +dnl Thomas Vander Stichele + +dnl $Id: as-compiler.m4,v 1.4 2004/06/01 09:44:19 thomasvs Exp $ + +dnl AS_COMPILER(COMPILER) +dnl will set variable COMPILER to +dnl - gcc +dnl - forte +dnl - (empty) if no guess could be made + +AC_DEFUN([AS_COMPILER], +[ + as_compiler= + AC_MSG_CHECKING(for compiler flavour) + + dnl is it gcc ? + if test "x$GCC" = "xyes"; then + as_compiler="gcc" + fi + + dnl is it forte ? + AC_TRY_RUN([ +int main +(int argc, char *argv[]) +{ +#ifdef __sun + return 0; +#else + return 1; +#endif +} + ], as_compiler="forte", ,) + + if test "x$as_compiler" = "x"; then + AC_MSG_RESULT([unknown !]) + else + AC_MSG_RESULT($as_compiler) + fi + [$1]=$as_compiler +]) diff --git a/common/m4/as-docbook.m4 b/common/m4/as-docbook.m4 new file mode 100644 index 0000000..2e27050 --- /dev/null +++ b/common/m4/as-docbook.m4 @@ -0,0 +1,78 @@ +dnl AS_DOCBOOK([, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl checks if xsltproc can build docbook documentation +dnl (which is possible if the catalog is set up properly +dnl I also tried checking for a specific version and type of docbook +dnl but xsltproc seemed to happily run anyway, so we can't check for that +dnl and version +dnl this macro takes inspiration from +dnl http://www.movement.uklinux.net/docs/docbook-autotools/configure.html +AC_DEFUN([AS_DOCBOOK], +[ + XSLTPROC_FLAGS=--nonet + DOCBOOK_ROOT= + TYPE_LC=xml + TYPE_UC=XML + DOCBOOK_VERSION=4.1.2 + + if test -n "$XML_CATALOG_FILES"; then + oldIFS=$IFS + IFS=' ' + for xml_catalog_file in $XML_CATALOG_FILES; do + if test -f $xml_catalog_file; then + XML_CATALOG=$xml_catalog_file + CAT_ENTRY_START='' + break + fi + done + IFS=$oldIFS + elif test ! -f /etc/xml/catalog; then + for i in /usr/share/sgml/docbook/stylesheet/xsl/nwalsh /usr/share/sgml/docbook/xsl-stylesheets/ /usr/local/share/xsl/docbook ; + do + if test -d "$i"; then + DOCBOOK_ROOT=$i + fi + done + else + XML_CATALOG=/etc/xml/catalog + CAT_ENTRY_START='' + fi + + dnl We need xsltproc to process the test + AC_CHECK_PROG(XSLTPROC,xsltproc,xsltproc,) + XSLTPROC_WORKS=no + if test -n "$XSLTPROC"; then + AC_MSG_CHECKING([whether xsltproc docbook processing works]) + + if test -n "$XML_CATALOG"; then + DB_FILE="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl" + else + DB_FILE="$DOCBOOK_ROOT/xhtml/docbook.xsl" + fi + $XSLTPROC $XSLTPROC_FLAGS $DB_FILE >/dev/null 2>&1 << END + + + + +END + if test "$?" = 0; then + XSLTPROC_WORKS=yes + fi + AC_MSG_RESULT($XSLTPROC_WORKS) + fi + + if test "x$XSLTPROC_WORKS" = "xyes"; then + dnl execute ACTION-IF-FOUND + ifelse([$1], , :, [$1]) + else + dnl execute ACTION-IF-NOT-FOUND + ifelse([$2], , :, [$2]) + fi + + AC_SUBST(XML_CATALOG) + AC_SUBST(XSLTPROC_FLAGS) + AC_SUBST(DOCBOOK_ROOT) + AC_SUBST(CAT_ENTRY_START) + AC_SUBST(CAT_ENTRY_END) +]) diff --git a/common/m4/as-gcc-inline-assembly.m4 b/common/m4/as-gcc-inline-assembly.m4 new file mode 100644 index 0000000..af32104 --- /dev/null +++ b/common/m4/as-gcc-inline-assembly.m4 @@ -0,0 +1,52 @@ +dnl as-gcc-inline-assembly.m4 0.1.0 + +dnl autostars m4 macro for detection of gcc inline assembly + +dnl David Schleef + +dnl $Id$ + +dnl AS_COMPILER_FLAG(ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) +dnl Tries to compile with the given CFLAGS. +dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, +dnl and ACTION-IF-NOT-ACCEPTED otherwise. + +AC_DEFUN([AS_GCC_INLINE_ASSEMBLY], +[ + AC_MSG_CHECKING([if compiler supports gcc-style inline assembly]) + + AC_TRY_COMPILE([], [ +#ifdef __GNUC_MINOR__ +#if (__GNUC__ * 1000 + __GNUC_MINOR__) < 3004 +#error GCC before 3.4 has critical bugs compiling inline assembly +#endif +#endif +__asm__ (""::) ], [flag_ok=yes], [flag_ok=no]) + + if test "X$flag_ok" = Xyes ; then + $1 + true + else + $2 + true + fi + AC_MSG_RESULT([$flag_ok]) +]) + + +AC_DEFUN([AS_GCC_ASM_POWERPC_FPU], +[ + AC_MSG_CHECKING([if compiler supports FPU instructions on PowerPC]) + + AC_TRY_COMPILE([], [__asm__ ("fadd 0,0,0"::) ], [flag_ok=yes], [flag_ok=no]) + + if test "X$flag_ok" = Xyes ; then + $1 + true + else + $2 + true + fi + AC_MSG_RESULT([$flag_ok]) +]) + diff --git a/common/m4/as-libtool-tags.m4 b/common/m4/as-libtool-tags.m4 new file mode 100644 index 0000000..06f0ae4 --- /dev/null +++ b/common/m4/as-libtool-tags.m4 @@ -0,0 +1,83 @@ +dnl as-libtool-tags.m4 0.1.4 + +dnl autostars m4 macro for selecting libtool "tags" (languages) + +dnl Andy Wingo does not claim credit for this macro +dnl backported from libtool 1.6 by Paolo Bonzini +dnl see http://lists.gnu.org/archive/html/libtool/2003-12/msg00007.html + +dnl $Id$ + +dnl AS_LIBTOOL_TAGS([tags...]) + +dnl example +dnl AS_LIBTOOL_TAGS([]) for only C (no fortran, etc) + +dnl When AC_LIBTOOL_TAGS is used, I redefine _LT_AC_TAGCONFIG +dnl to be more similar to the libtool 1.6 implementation, which +dnl uses an m4 loop and m4 case instead of a shell loop. This +dnl way the CXX/GCJ/F77/RC tests are not always expanded. + +dnl AS_LIBTOOL_TAGS +dnl --------------- +dnl tags to enable +AC_DEFUN([AS_LIBTOOL_TAGS], +[m4_define([_LT_TAGS],[$1]) +m4_define([_LT_AC_TAGCONFIG], [ + # redefined LT AC TAGCONFIG + if test -f "$ltmain"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + + AC_FOREACH([_LT_TAG], _LT_TAGS, + echo THOMAS: tag _LT_TAG + [m4_case(_LT_TAG, + [CXX], [ + if test -n "$CXX" && test "X$CXX" != "Xno"; then + echo "THOMAS: YAY CXX" + AC_LIBTOOL_LANG_CXX_CONFIG + available_tags="$available_tags _LT_TAG" + fi], + [F77], [ + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + available_tags="$available_tags _LT_TAG" + fi], + [GCJ], [ + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + available_tags="$available_tags _LT_TAG" + fi], + [RC], [ + if test -n "$RC" && test "X$RC" != "Xno"; then + AC_LIBTOOL_LANG_RC_CONFIG + available_tags="$available_tags _LT_TAG" + fi], + [m4_errprintn(m4_location[: error: invalid tag name: ]"_LT_TAG") + m4_exit(1)]) + ]) + echo THOMAS: available tags: $available_tags + fi + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + AC_MSG_NOTICE([updated available libtool tags with $available_tags.]) + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + + fi + +])dnl _LT_AC_TAG_CONFIG +]) diff --git a/common/m4/as-libtool.m4 b/common/m4/as-libtool.m4 new file mode 100644 index 0000000..3b16095 --- /dev/null +++ b/common/m4/as-libtool.m4 @@ -0,0 +1,46 @@ +dnl as-libtool.m4 0.1.4 + +dnl autostars m4 macro for libtool versioning + +dnl Thomas Vander Stichele + +dnl $Id: as-libtool.m4,v 1.10 2005/10/15 13:44:23 thomasvs Exp $ + +dnl AS_LIBTOOL(PREFIX, CURRENT, REVISION, AGE, [RELEASE]) + +dnl example +dnl AS_LIBTOOL(GST, 2, 0, 0) + +dnl this macro +dnl - defines [$PREFIX]_CURRENT, REVISION and AGE +dnl - defines [$PREFIX]_LIBVERSION +dnl - defines [$PREFIX]_LT_LDFLAGS to set versioning +dnl - AC_SUBST's them all + +dnl if RELEASE is given, then add a -release option to the LDFLAGS +dnl with the given release version +dnl then use [$PREFIX]_LT_LDFLAGS in the relevant Makefile.am's + +dnl call AM_PROG_LIBTOOL after this call + +AC_DEFUN([AS_LIBTOOL], +[ + [$1]_CURRENT=[$2] + [$1]_REVISION=[$3] + [$1]_AGE=[$4] + [$1]_LIBVERSION=[$2]:[$3]:[$4] + AC_SUBST([$1]_CURRENT) + AC_SUBST([$1]_REVISION) + AC_SUBST([$1]_AGE) + AC_SUBST([$1]_LIBVERSION) + + [$1]_LT_LDFLAGS="$[$1]_LT_LDFLAGS -version-info $[$1]_LIBVERSION" + if test ! -z "[$5]" + then + [$1]_LT_LDFLAGS="$[$1]_LT_LDFLAGS -release [$5]" + fi + AC_SUBST([$1]_LT_LDFLAGS) + + LT_PREREQ([2.2.6]) + LT_INIT([dlopen win32-dll disable-static]) +]) diff --git a/common/m4/as-python.m4 b/common/m4/as-python.m4 new file mode 100644 index 0000000..eb9b175 --- /dev/null +++ b/common/m4/as-python.m4 @@ -0,0 +1,152 @@ +## ------------------------ +## Python file handling +## From Andrew Dalke +## Updated by James Henstridge +## Updated by Andy Wingo to loop through possible pythons +## ------------------------ + +# AS_PATH_PYTHON([MINIMUM-VERSION]) + +# Adds support for distributing Python modules and packages. To +# install modules, copy them to $(pythondir), using the python_PYTHON +# automake variable. To install a package with the same name as the +# automake package, install to $(pkgpythondir), or use the +# pkgpython_PYTHON automake variable. + +# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as +# locations to install python extension modules (shared libraries). +# Another macro is required to find the appropriate flags to compile +# extension modules. + +# If your package is configured with a different prefix to python, +# users will have to add the install directory to the PYTHONPATH +# environment variable, or create a .pth file (see the python +# documentation for details). + +# If the MINIMUM-VERSION argument is passed, AS_PATH_PYTHON will +# cause an error if the version of python installed on the system +# doesn't meet the requirement. MINIMUM-VERSION should consist of +# numbers and dots only. + +# Updated to loop over all possible python binaries by Andy Wingo +# +# Updated to only warn and unset PYTHON if no good one is found + +AC_DEFUN([AS_PATH_PYTHON], + [ + dnl Find a version of Python. I could check for python versions 1.4 + dnl or earlier, but the default installation locations changed from + dnl $prefix/lib/site-python in 1.4 to $prefix/lib/python1.5/site-packages + dnl in 1.5, and I don't want to maintain that logic. + + dnl should we do the version check? + PYTHON_CANDIDATES="python python2.2 python2.1 python2.0 python2 \ + python1.6 python1.5" + ifelse([$1],[], + [AC_PATH_PROG(PYTHON, $PYTHON_CANDIDATES)], + [ + AC_MSG_NOTICE(Looking for Python version >= $1) + changequote(<<, >>)dnl + prog=" +import sys, string +minver = '$1' +# split string by '.' and convert to numeric +minver_info = map(string.atoi, string.split(minver, '.')) +# we can now do comparisons on the two lists: +if sys.version_info >= tuple(minver_info): + sys.exit(0) +else: + sys.exit(1)" + changequote([, ])dnl + + python_good=false + for python_candidate in $PYTHON_CANDIDATES; do + unset PYTHON + AC_PATH_PROG(PYTHON, $python_candidate) 1> /dev/null 2> /dev/null + + if test "x$PYTHON" = "x"; then continue; fi + + if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC; then + AC_MSG_CHECKING(["$PYTHON":]) + AC_MSG_RESULT([okay]) + python_good=true + break; + else + dnl clear the cache val + unset ac_cv_path_PYTHON + fi + done + ]) + + if test "$python_good" != "true"; then + AC_MSG_WARN([No suitable version of python found]) + PYTHON= + else + + AC_MSG_CHECKING([local Python configuration]) + + dnl Query Python for its version number. Getting [:3] seems to be + dnl the best way to do this; it's what "site.py" does in the standard + dnl library. Need to change quote character because of [:3] + + AC_SUBST(PYTHON_VERSION) + changequote(<<, >>)dnl + PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[:3]"` + changequote([, ])dnl + + + dnl Use the values of $prefix and $exec_prefix for the corresponding + dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made + dnl distinct variables so they can be overridden if need be. However, + dnl general consensus is that you shouldn't need this ability. + + AC_SUBST(PYTHON_PREFIX) + PYTHON_PREFIX='${prefix}' + + AC_SUBST(PYTHON_EXEC_PREFIX) + PYTHON_EXEC_PREFIX='${exec_prefix}' + + dnl At times (like when building shared libraries) you may want + dnl to know which OS platform Python thinks this is. + + AC_SUBST(PYTHON_PLATFORM) + PYTHON_PLATFORM=`$PYTHON -c "import sys; print sys.platform"` + + + dnl Set up 4 directories: + + dnl pythondir -- where to install python scripts. This is the + dnl site-packages directory, not the python standard library + dnl directory like in previous automake betas. This behaviour + dnl is more consistent with lispdir.m4 for example. + dnl + dnl Also, if the package prefix isn't the same as python's prefix, + dnl then the old $(pythondir) was pretty useless. + + AC_SUBST(pythondir) + pythondir=$PYTHON_PREFIX"/lib/python"$PYTHON_VERSION/site-packages + + dnl pkgpythondir -- $PACKAGE directory under pythondir. Was + dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is + dnl more consistent with the rest of automake. + dnl Maybe this should be put in python.am? + + AC_SUBST(pkgpythondir) + pkgpythondir=\${pythondir}/$PACKAGE + + dnl pyexecdir -- directory for installing python extension modules + dnl (shared libraries) Was PYTHON_SITE_EXEC in previous betas. + + AC_SUBST(pyexecdir) + pyexecdir=$PYTHON_EXEC_PREFIX"/lib/python"$PYTHON_VERSION/site-packages + + dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) + dnl Maybe this should be put in python.am? + + AC_SUBST(pkgpyexecdir) + pkgpyexecdir=\${pyexecdir}/$PACKAGE + + AC_MSG_RESULT([looks good]) + + fi +]) diff --git a/common/m4/as-version.m4 b/common/m4/as-version.m4 new file mode 100644 index 0000000..22ff774 --- /dev/null +++ b/common/m4/as-version.m4 @@ -0,0 +1,75 @@ +dnl as-version.m4 0.2.0 + +dnl autostars m4 macro for versioning + +dnl Thomas Vander Stichele + +dnl $Id: as-version.m4,v 1.15 2006/04/01 09:40:24 thomasvs Exp $ + +dnl AS_VERSION + +dnl example +dnl AS_VERSION + +dnl this macro +dnl - AC_SUBST's PACKAGE_VERSION_MAJOR, _MINOR, _MICRO +dnl - AC_SUBST's PACKAGE_VERSION_RELEASE, +dnl which can be used for rpm release fields +dnl - doesn't call AM_INIT_AUTOMAKE anymore because it prevents +dnl maintainer mode from running correctly +dnl +dnl don't forget to put #undef PACKAGE_VERSION_RELEASE in acconfig.h +dnl if you use acconfig.h + +AC_DEFUN([AS_VERSION], +[ + PACKAGE_VERSION_MAJOR=$(echo AC_PACKAGE_VERSION | cut -d'.' -f1) + PACKAGE_VERSION_MINOR=$(echo AC_PACKAGE_VERSION | cut -d'.' -f2) + PACKAGE_VERSION_MICRO=$(echo AC_PACKAGE_VERSION | cut -d'.' -f3) + + AC_SUBST(PACKAGE_VERSION_MAJOR) + AC_SUBST(PACKAGE_VERSION_MINOR) + AC_SUBST(PACKAGE_VERSION_MICRO) +]) + +dnl AS_NANO(ACTION-IF-NANO-NON-NULL, [ACTION-IF-NANO-NULL]) + +dnl requires AC_INIT to be called before +dnl For projects using a fourth or nano number in your versioning to indicate +dnl development or prerelease snapshots, this macro allows the build to be +dnl set up differently accordingly. + +dnl this macro: +dnl - parses AC_PACKAGE_VERSION, set by AC_INIT, and extracts the nano number +dnl - sets the variable PACKAGE_VERSION_NANO +dnl - sets the variable PACKAGE_VERSION_RELEASE, which can be used +dnl for rpm release fields +dnl - executes ACTION-IF-NANO-NON-NULL or ACTION-IF-NANO-NULL + +dnl example: +dnl AS_NANO(RELEASE="yes", RELEASE="no") + +AC_DEFUN([AS_NANO], +[ + AC_MSG_CHECKING(nano version) + + NANO=$(echo AC_PACKAGE_VERSION | cut -d'.' -f4) + + if test x"$NANO" = x || test "x$NANO" = "x0" ; then + AC_MSG_RESULT([0 (release)]) + NANO=0 + PACKAGE_VERSION_RELEASE=1 + ifelse([$1], , :, [$1]) + else + AC_MSG_RESULT($NANO) + PACKAGE_VERSION_RELEASE=0.`date +%Y%m%d.%H%M%S` + if test "x$NANO" != "x1" ; then + ifelse([$1], , :, [$1]) + else + ifelse([$2], , :, [$2]) + fi + fi + PACKAGE_VERSION_NANO=$NANO + AC_SUBST(PACKAGE_VERSION_NANO) + AC_SUBST(PACKAGE_VERSION_RELEASE) +]) diff --git a/common/m4/ax_create_stdint_h.m4 b/common/m4/ax_create_stdint_h.m4 new file mode 100644 index 0000000..13bf699 --- /dev/null +++ b/common/m4/ax_create_stdint_h.m4 @@ -0,0 +1,734 @@ +##### http://autoconf-archive.cryp.to/ax_create_stdint_h.html +# +# SYNOPSIS +# +# AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])] +# +# DESCRIPTION +# +# the "ISO C9X: 7.18 Integer types " section requires the +# existence of an include file that defines a set of +# typedefs, especially uint8_t,int32_t,uintptr_t. Many older +# installations will not provide this file, but some will have the +# very same definitions in . In other enviroments we can +# use the inet-types in which would define the typedefs +# int8_t and u_int8_t respectivly. +# +# This macros will create a local "_stdint.h" or the headerfile given +# as an argument. In many cases that file will just "#include +# " or "#include ", while in other environments +# it will provide the set of basic 'stdint's definitions/typedefs: +# +# int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t +# int_least32_t.. int_fast32_t.. intmax_t +# +# which may or may not rely on the definitions of other files, or +# using the AC_CHECK_SIZEOF macro to determine the actual sizeof each +# type. +# +# if your header files require the stdint-types you will want to +# create an installable file mylib-int.h that all your other +# installable header may include. So if you have a library package +# named "mylib", just use +# +# AX_CREATE_STDINT_H(mylib-int.h) +# +# in configure.ac and go to install that very header file in +# Makefile.am along with the other headers (mylib.h) - and the +# mylib-specific headers can simply use "#include " to +# obtain the stdint-types. +# +# Remember, if the system already had a valid , the +# generated file will include it directly. No need for fuzzy +# HAVE_STDINT_H things... (oops, GCC 4.2.x has deliberatly disabled +# its stdint.h for non-c99 compilation and the c99-mode is not the +# default. Therefore this macro will not use the compiler's stdint.h +# - please complain to the GCC developers). +# +# LAST MODIFICATION +# +# 2007-06-27 +# +# COPYLEFT +# +# Copyright (c) 2007 Guido U. Draheim +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# +# As a special exception, the respective Autoconf Macro's copyright +# owner gives unlimited permission to copy, distribute and modify the +# configure scripts that are the output of Autoconf when processing +# the Macro. You need not follow the terms of the GNU General Public +# License when using or distributing such scripts, even though +# portions of the text of the Macro appear in them. The GNU General +# Public License (GPL) does govern all other use of the material that +# constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you +# make and distribute a modified version of the Autoconf Macro, you +# may extend this special exception to the GPL to apply to your +# modified version as well. + +AC_DEFUN([AX_CHECK_DATA_MODEL],[ + AC_CHECK_SIZEOF(char) + AC_CHECK_SIZEOF(short) + AC_CHECK_SIZEOF(int) + AC_CHECK_SIZEOF(long) + AC_CHECK_SIZEOF(void*) + ac_cv_char_data_model="" + ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char" + ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short" + ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int" + ac_cv_long_data_model="" + ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int" + ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long" + ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp" + AC_MSG_CHECKING([data model]) + case "$ac_cv_char_data_model/$ac_cv_long_data_model" in + 122/242) ac_cv_data_model="IP16" ; n="standard 16bit machine" ;; + 122/244) ac_cv_data_model="LP32" ; n="standard 32bit machine" ;; + 122/*) ac_cv_data_model="i16" ; n="unusual int16 model" ;; + 124/444) ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;; + 124/488) ac_cv_data_model="LP64" ; n="standard 64bit unixish" ;; + 124/448) ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;; + 124/*) ac_cv_data_model="i32" ; n="unusual int32 model" ;; + 128/888) ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;; + 128/*) ac_cv_data_model="i64" ; n="unusual int64 model" ;; + 222/*2) ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;; + 333/*3) ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;; + 444/*4) ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;; + 666/*6) ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;; + 888/*8) ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;; + 222/*|333/*|444/*|666/*|888/*) : + ac_cv_data_model="iDSP" ; n="unusual dsptype" ;; + *) ac_cv_data_model="none" ; n="very unusual model" ;; + esac + AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)]) +]) + +dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF]) +AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[ +AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[ + ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h) + AC_MSG_RESULT([(..)]) + for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h sys/types.h]) + do + unset ac_cv_type_uintptr_t + unset ac_cv_type_uint64_t + AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) + m4_ifvaln([$2],[$2]) break + done + AC_MSG_CHECKING([for stdint uintptr_t]) + ]) +]) + +AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[ +AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[ + ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h) + AC_MSG_RESULT([(..)]) + for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h sys/types.h stdint.h]) + do + unset ac_cv_type_uint32_t + unset ac_cv_type_uint64_t + AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) + m4_ifvaln([$2],[$2]) break + break; + done + AC_MSG_CHECKING([for stdint uint32_t]) + ]) +]) + +AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[ +AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[ + ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h) + AC_MSG_RESULT([(..)]) + for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do + unset ac_cv_type_u_int32_t + unset ac_cv_type_u_int64_t + AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>]) + AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>]) + m4_ifvaln([$2],[$2]) break + break; + done + AC_MSG_CHECKING([for stdint u_int32_t]) + ]) +]) + +AC_DEFUN([AX_CREATE_STDINT_H], +[# ------ AX CREATE STDINT H ------------------------------------- +AC_MSG_CHECKING([for stdint types]) +ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)` +# try to shortcircuit - if the default include path of the compiler +# can find a "stdint.h" header then we assume that all compilers can. +AC_CACHE_VAL([ac_cv_header_stdint_t],[ +old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS="" +old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS="" +old_CFLAGS="$CFLAGS" ; CFLAGS="" +AC_TRY_COMPILE([#include ],[int_least32_t v = 0;], +[ac_cv_stdint_result="(assuming C99 compatible system)" + ac_cv_header_stdint_t="stdint.h"; ], +[ac_cv_header_stdint_t=""]) +if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then +CFLAGS="-std=c99" +AC_TRY_COMPILE([#include ],[int_least32_t v = 0;], +[AC_MSG_WARN(your GCC compiler has a defunct stdint.h for its default-mode)]) +fi +CXXFLAGS="$old_CXXFLAGS" +CPPFLAGS="$old_CPPFLAGS" +CFLAGS="$old_CFLAGS" ]) + +v="... $ac_cv_header_stdint_h" +if test "$ac_stdint_h" = "stdint.h" ; then + AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)]) +elif test "$ac_stdint_h" = "inttypes.h" ; then + AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)]) +elif test "_$ac_cv_header_stdint_t" = "_" ; then + AC_MSG_RESULT([(putting them into $ac_stdint_h)$v]) +else + ac_cv_header_stdint="$ac_cv_header_stdint_t" + AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)]) +fi + +if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit.. + +dnl .....intro message done, now do a few system checks..... +dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type, +dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW +dnl instead that is triggered with 3 or more arguments (see types.m4) + +inttype_headers=`echo $2 | sed -e 's/,/ /g'` + +ac_cv_stdint_result="(no helpful system typedefs seen)" +AX_CHECK_HEADER_STDINT_X(dnl + stdint.h inttypes.h sys/inttypes.h $inttype_headers, + ac_cv_stdint_result="(seen uintptr_t$and64 in $i)") + +if test "_$ac_cv_header_stdint_x" = "_" ; then +AX_CHECK_HEADER_STDINT_O(dnl, + inttypes.h sys/inttypes.h stdint.h $inttype_headers, + ac_cv_stdint_result="(seen uint32_t$and64 in $i)") +fi + +if test "_$ac_cv_header_stdint_x" = "_" ; then +if test "_$ac_cv_header_stdint_o" = "_" ; then +AX_CHECK_HEADER_STDINT_U(dnl, + sys/types.h inttypes.h sys/inttypes.h $inttype_headers, + ac_cv_stdint_result="(seen u_int32_t$and64 in $i)") +fi fi + +dnl if there was no good C99 header file, do some typedef checks... +if test "_$ac_cv_header_stdint_x" = "_" ; then + AC_MSG_CHECKING([for stdint datatype model]) + AC_MSG_RESULT([(..)]) + AX_CHECK_DATA_MODEL +fi + +if test "_$ac_cv_header_stdint_x" != "_" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_x" +elif test "_$ac_cv_header_stdint_o" != "_" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_o" +elif test "_$ac_cv_header_stdint_u" != "_" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_u" +else + ac_cv_header_stdint="stddef.h" +fi + +AC_MSG_CHECKING([for extra inttypes in chosen header]) +AC_MSG_RESULT([($ac_cv_header_stdint)]) +dnl see if int_least and int_fast types are present in _this_ header. +unset ac_cv_type_int_least32_t +unset ac_cv_type_int_fast32_t +AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>]) +AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>]) +AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>]) + +fi # shortcircut to system "stdint.h" +# ------------------ PREPARE VARIABLES ------------------------------ +if test "$GCC" = "yes" ; then +ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1` +else +ac_cv_stdint_message="using $CC" +fi + +AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl +$ac_cv_stdint_result]) + +dnl ----------------------------------------------------------------- +# ----------------- DONE inttypes.h checks START header ------------- +AC_CONFIG_COMMANDS([$ac_stdint_h],[ +AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h) +ac_stdint=$tmp/_stdint.h + +echo "#ifndef" $_ac_stdint_h >$ac_stdint +echo "#define" $_ac_stdint_h "1" >>$ac_stdint +echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint +echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint +echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint +if test "_$ac_cv_header_stdint_t" != "_" ; then +echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint +echo "#include " >>$ac_stdint +echo "#endif" >>$ac_stdint +echo "#endif" >>$ac_stdint +else + +cat >>$ac_stdint < +#else +#include + +/* .................... configured part ............................ */ + +STDINT_EOF + +echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint +if test "_$ac_cv_header_stdint_x" != "_" ; then + ac_header="$ac_cv_header_stdint_x" + echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint +else + echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint +fi + +echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint +if test "_$ac_cv_header_stdint_o" != "_" ; then + ac_header="$ac_cv_header_stdint_o" + echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint +else + echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint +fi + +echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint +if test "_$ac_cv_header_stdint_u" != "_" ; then + ac_header="$ac_cv_header_stdint_u" + echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint +else + echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint +fi + +echo "" >>$ac_stdint + +if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then + echo "#include <$ac_header>" >>$ac_stdint + echo "" >>$ac_stdint +fi fi + +echo "/* which 64bit typedef has been found */" >>$ac_stdint +if test "$ac_cv_type_uint64_t" = "yes" ; then +echo "#define _STDINT_HAVE_UINT64_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint +fi +if test "$ac_cv_type_u_int64_t" = "yes" ; then +echo "#define _STDINT_HAVE_U_INT64_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint +fi +echo "" >>$ac_stdint + +echo "/* which type model has been detected */" >>$ac_stdint +if test "_$ac_cv_char_data_model" != "_" ; then +echo "#define _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint +echo "#define _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint +else +echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint +echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint +fi +echo "" >>$ac_stdint + +echo "/* whether int_least types were detected */" >>$ac_stdint +if test "$ac_cv_type_int_least32_t" = "yes"; then +echo "#define _STDINT_HAVE_INT_LEAST32_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint +fi +echo "/* whether int_fast types were detected */" >>$ac_stdint +if test "$ac_cv_type_int_fast32_t" = "yes"; then +echo "#define _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint +fi +echo "/* whether intmax_t type was detected */" >>$ac_stdint +if test "$ac_cv_type_intmax_t" = "yes"; then +echo "#define _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint +fi +echo "" >>$ac_stdint + + cat >>$ac_stdint <= 199901L +#define _HAVE_UINT64_T +#define _HAVE_LONGLONG_UINT64_T +typedef long long int64_t; +typedef unsigned long long uint64_t; + +#elif !defined __STRICT_ANSI__ +#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ +#define _HAVE_UINT64_T +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__ +/* note: all ELF-systems seem to have loff-support which needs 64-bit */ +#if !defined _NO_LONGLONG +#define _HAVE_UINT64_T +#define _HAVE_LONGLONG_UINT64_T +typedef long long int64_t; +typedef unsigned long long uint64_t; +#endif + +#elif defined __alpha || (defined __mips && defined _ABIN32) +#if !defined _NO_LONGLONG +typedef long int64_t; +typedef unsigned long uint64_t; +#endif + /* compiler/cpu type to define int64_t */ +#endif +#endif +#endif + +#if defined _STDINT_HAVE_U_INT_TYPES +/* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */ +typedef u_int8_t uint8_t; +typedef u_int16_t uint16_t; +typedef u_int32_t uint32_t; + +/* glibc compatibility */ +#ifndef __int8_t_defined +#define __int8_t_defined +#endif +#endif + +#ifdef _STDINT_NEED_INT_MODEL_T +/* we must guess all the basic types. Apart from byte-adressable system, */ +/* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */ +/* (btw, those nibble-addressable systems are way off, or so we assume) */ + +dnl /* have a look at "64bit and data size neutrality" at */ +dnl /* http://unix.org/version2/whatsnew/login_64bit.html */ +dnl /* (the shorthand "ILP" types always have a "P" part) */ + +#if defined _STDINT_BYTE_MODEL +#if _STDINT_LONG_MODEL+0 == 242 +/* 2:4:2 = IP16 = a normal 16-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef long int32_t; +#endif +#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444 +/* 2:4:4 = LP32 = a 32-bit system derived from a 16-bit */ +/* 4:4:4 = ILP32 = a normal 32-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +#endif +#elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488 +/* 4:8:4 = IP32 = a 32-bit system prepared for 64-bit */ +/* 4:8:8 = LP64 = a normal 64-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +#endif +/* this system has a "long" of 64bit */ +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +typedef unsigned long uint64_t; +typedef long int64_t; +#endif +#elif _STDINT_LONG_MODEL+0 == 448 +/* LLP64 a 64-bit system derived from a 32-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +#endif +/* assuming the system has a "long long" */ +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +#define _HAVE_LONGLONG_UINT64_T +typedef unsigned long long uint64_t; +typedef long long int64_t; +#endif +#else +#define _STDINT_NO_INT32_T +#endif +#else +#define _STDINT_NO_INT8_T +#define _STDINT_NO_INT32_T +#endif +#endif + +/* + * quote from SunOS-5.8 sys/inttypes.h: + * Use at your own risk. As of February 1996, the committee is squarely + * behind the fixed sized types; the "least" and "fast" types are still being + * discussed. The probability that the "fast" types may be removed before + * the standard is finalized is high enough that they are not currently + * implemented. + */ + +#if defined _STDINT_NEED_INT_LEAST_T +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +#ifdef _HAVE_UINT64_T +typedef int64_t int_least64_t; +#endif + +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +#ifdef _HAVE_UINT64_T +typedef uint64_t uint_least64_t; +#endif + /* least types */ +#endif + +#if defined _STDINT_NEED_INT_FAST_T +typedef int8_t int_fast8_t; +typedef int int_fast16_t; +typedef int32_t int_fast32_t; +#ifdef _HAVE_UINT64_T +typedef int64_t int_fast64_t; +#endif + +typedef uint8_t uint_fast8_t; +typedef unsigned uint_fast16_t; +typedef uint32_t uint_fast32_t; +#ifdef _HAVE_UINT64_T +typedef uint64_t uint_fast64_t; +#endif + /* fast types */ +#endif + +#ifdef _STDINT_NEED_INTMAX_T +#ifdef _HAVE_UINT64_T +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; +#else +typedef long intmax_t; +typedef unsigned long uintmax_t; +#endif +#endif + +#ifdef _STDINT_NEED_INTPTR_T +#ifndef __intptr_t_defined +#define __intptr_t_defined +/* we encourage using "long" to store pointer values, never use "int" ! */ +#if _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484 +typedef unsigned int uintptr_t; +typedef int intptr_t; +#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444 +typedef unsigned long uintptr_t; +typedef long intptr_t; +#elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T +typedef uint64_t uintptr_t; +typedef int64_t intptr_t; +#else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */ +typedef unsigned long uintptr_t; +typedef long intptr_t; +#endif +#endif +#endif + +/* The ISO C99 standard specifies that in C++ implementations these + should only be defined if explicitly requested. */ +#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS +#ifndef UINT32_C + +/* Signed. */ +# define INT8_C(c) c +# define INT16_C(c) c +# define INT32_C(c) c +# ifdef _HAVE_LONGLONG_UINT64_T +# define INT64_C(c) c ## L +# else +# define INT64_C(c) c ## LL +# endif + +/* Unsigned. */ +# define UINT8_C(c) c ## U +# define UINT16_C(c) c ## U +# define UINT32_C(c) c ## U +# ifdef _HAVE_LONGLONG_UINT64_T +# define UINT64_C(c) c ## UL +# else +# define UINT64_C(c) c ## ULL +# endif + +/* Maximal type. */ +# ifdef _HAVE_LONGLONG_UINT64_T +# define INTMAX_C(c) c ## L +# define UINTMAX_C(c) c ## UL +# else +# define INTMAX_C(c) c ## LL +# define UINTMAX_C(c) c ## ULL +# endif + + /* literalnumbers */ +#endif +#endif + +/* These limits are merily those of a two complement byte-oriented system */ + +/* Minimum of signed integral types. */ +# define INT8_MIN (-128) +# define INT16_MIN (-32767-1) +# define INT32_MIN (-2147483647-1) +# define INT64_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum of signed integral types. */ +# define INT8_MAX (127) +# define INT16_MAX (32767) +# define INT32_MAX (2147483647) +# define INT64_MAX (__INT64_C(9223372036854775807)) + +/* Maximum of unsigned integral types. */ +# define UINT8_MAX (255) +# define UINT16_MAX (65535) +# define UINT32_MAX (4294967295U) +# define UINT64_MAX (__UINT64_C(18446744073709551615)) + +/* Minimum of signed integral types having a minimum size. */ +# define INT_LEAST8_MIN INT8_MIN +# define INT_LEAST16_MIN INT16_MIN +# define INT_LEAST32_MIN INT32_MIN +# define INT_LEAST64_MIN INT64_MIN +/* Maximum of signed integral types having a minimum size. */ +# define INT_LEAST8_MAX INT8_MAX +# define INT_LEAST16_MAX INT16_MAX +# define INT_LEAST32_MAX INT32_MAX +# define INT_LEAST64_MAX INT64_MAX + +/* Maximum of unsigned integral types having a minimum size. */ +# define UINT_LEAST8_MAX UINT8_MAX +# define UINT_LEAST16_MAX UINT16_MAX +# define UINT_LEAST32_MAX UINT32_MAX +# define UINT_LEAST64_MAX UINT64_MAX + + /* shortcircuit*/ +#endif + /* once */ +#endif +#endif +STDINT_EOF +fi + if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then + AC_MSG_NOTICE([$ac_stdint_h is unchanged]) + else + ac_dir=`AS_DIRNAME(["$ac_stdint_h"])` + AS_MKDIR_P(["$ac_dir"]) + rm -f $ac_stdint_h + mv $ac_stdint $ac_stdint_h + fi +],[# variables for create stdint.h replacement +PACKAGE="$PACKAGE" +VERSION="$VERSION" +ac_stdint_h="$ac_stdint_h" +_ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h) +ac_cv_stdint_message="$ac_cv_stdint_message" +ac_cv_header_stdint_t="$ac_cv_header_stdint_t" +ac_cv_header_stdint_x="$ac_cv_header_stdint_x" +ac_cv_header_stdint_o="$ac_cv_header_stdint_o" +ac_cv_header_stdint_u="$ac_cv_header_stdint_u" +ac_cv_type_uint64_t="$ac_cv_type_uint64_t" +ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t" +ac_cv_char_data_model="$ac_cv_char_data_model" +ac_cv_long_data_model="$ac_cv_long_data_model" +ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t" +ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t" +ac_cv_type_intmax_t="$ac_cv_type_intmax_t" +]) +]) diff --git a/common/m4/check.m4 b/common/m4/check.m4 new file mode 100644 index 0000000..afd26eb --- /dev/null +++ b/common/m4/check.m4 @@ -0,0 +1,181 @@ +dnl _AM_TRY_CHECK(MINIMUM-VERSION, EXTRA-CFLAGS, EXTRA-LIBS, CHECK-LIB-NAME +dnl [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Test for check, and define CHECK_CFLAGS and CHECK_LIBS +dnl Done this way because of the brokenness that is +dnl https://launchpad.net/distros/ubuntu/+source/check/+bug/5840 +dnl + +AC_DEFUN([_AM_TRY_CHECK], +[ + min_check_version=$1 + extra_cflags=$2 + extra_libs=$3 + check_lib_name=$4 + + CHECK_CFLAGS="$extra_cflags" + CHECK_LIBS="$extra_libs -l$check_lib_name" + + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + + CFLAGS="$CFLAGS $CHECK_CFLAGS" + LIBS="$CHECK_LIBS $LIBS" + + AC_MSG_CHECKING(for check named $check_lib_name - version >= $min_check_version) + + rm -f conf.check-test + dnl unset no_check, since in our second run it would have been set to yes + dnl before + no_check= + AC_TRY_RUN([ +#include +#include + +#include + +int main () +{ + int major, minor, micro; + char *tmp_version; + + system ("touch conf.check-test"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = strdup("$min_check_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_check_version"); + return 1; + } + + if ((CHECK_MAJOR_VERSION != check_major_version) || + (CHECK_MINOR_VERSION != check_minor_version) || + (CHECK_MICRO_VERSION != check_micro_version)) + { + printf("\n*** The check header file (version %d.%d.%d) does not match\n", + CHECK_MAJOR_VERSION, CHECK_MINOR_VERSION, CHECK_MICRO_VERSION); + printf("*** the check library (version %d.%d.%d).\n", + check_major_version, check_minor_version, check_micro_version); + return 1; + } + + if ((check_major_version > major) || + ((check_major_version == major) && (check_minor_version > minor)) || + ((check_major_version == major) && (check_minor_version == minor) && (check_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of check (%d.%d.%d) was found.\n", + check_major_version, check_minor_version, check_micro_version); + printf("*** You need a version of check being at least %d.%d.%d.\n", major, minor, micro); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the check library and header\n"); + printf("*** file is being found. Rerun configure with the --with-check=PATH option\n"); + printf("*** to specify the prefix where the correct version was installed.\n"); + } + + return 1; +} +],, no_check=yes, [echo $ac_n "cross compiling; assumed OK... $ac_c"]) + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + + if test "x$no_check" = x ; then + AC_MSG_RESULT(yes) + ifelse([$5], , :, [$5]) + else + AC_MSG_RESULT(no) + if test -f conf.check-test ; then + : + else + echo "*** Could not run check test program, checking why..." + CFLAGS="$CFLAGS $CHECK_CFLAGS" + LIBS="$CHECK_LIBS $LIBS" + AC_TRY_LINK([ +#include +#include + +#include +], , [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding check. You'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for" + echo "*** the exact error that occured." ]) + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + + CHECK_CFLAGS="" + CHECK_LIBS="" + + rm -f conf.check-test + ifelse([$6], , AC_MSG_ERROR([check not found]), [$6]) + fi +]) + + +dnl AM_PATH_CHECK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for check, and define CHECK_CFLAGS and CHECK_LIBS +dnl + +AC_DEFUN([AM_PATH_CHECK], +[ + AC_ARG_WITH(check, + [ --with-check=PATH prefix where check is installed [default=auto]]) + + AC_ARG_WITH(checklibname, + AC_HELP_STRING([--with-check-lib-name=NAME], + [name of the PIC check library (default=check)])) + + min_check_version=ifelse([$1], ,0.8.2,$1) + + if test x$with_check = xno; then + AC_MSG_RESULT(disabled) + ifelse([$3], , AC_MSG_ERROR([disabling check is not supported]), [$3]) + else + if test "x$with_check" != x; then + CHECK_EXTRA_CFLAGS="-I$with_check/include" + CHECK_EXTRA_LIBS="-L$with_check/lib" + else + CHECK_EXTRA_CFLAGS="" + CHECK_EXTRA_LIBS="" + fi + + if test x$with_checklibname = x; then + _AM_TRY_CHECK($min_check_version, $CHECK_EXTRA_CFLAGS, $CHECK_EXTRA_LIBS, + check_pic, [have_check=true], [have_check=false]) + if test x$have_check = xtrue; then + ifelse([$2], , :, [$2]) + else + _AM_TRY_CHECK($min_check_version, $CHECK_EXTRA_CFLAGS, $CHECK_EXTRA_LIBS, + check, [have_check=true], [have_check=false]) + if test x$have_check = xtrue; then + ifelse([$2], , :, [$2]) + else + ifelse([$3], , AC_MSG_ERROR([check not found]), [$3]) + fi + fi + else + _AM_TRY_CHECK($min_check_version, $CHECK_EXTRA_CFLAGS, $CHECK_EXTRA_LIBS, + $with_checklibname, [have_check=true], [have_check=false]) + if test x$have_check = xtrue; then + ifelse([$2], , :, [$2]) + else + ifelse([$3], , AC_MSG_ERROR([check not found]), [$3]) + fi + fi + + AC_SUBST(CHECK_CFLAGS) + AC_SUBST(CHECK_LIBS) + rm -f conf.check-test + fi +]) diff --git a/common/m4/glib-gettext.m4 b/common/m4/glib-gettext.m4 new file mode 100644 index 0000000..f8d442f --- /dev/null +++ b/common/m4/glib-gettext.m4 @@ -0,0 +1,432 @@ +# Copyright (C) 1995-2002 Free Software Foundation, Inc. +# Copyright (C) 2001-2003,2004 Red Hat, Inc. +# +# This file is free software, distributed under the terms of the GNU +# General Public License. As a special exception to the GNU General +# Public License, this file may be distributed as part of a program +# that contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995, 1996 +# +# Modified to never use included libintl. +# Owen Taylor , 12/15/1998 +# +# Major rework to remove unused code +# Owen Taylor , 12/11/2002 +# +# Added better handling of ALL_LINGUAS from GNU gettext version +# written by Bruno Haible, Owen Taylor 5/30/3002 +# +# Modified to require ngettext +# Matthias Clasen 08/06/2004 +# +# We need this here as well, since someone might use autoconf-2.5x +# to configure GLib then an older version to configure a package +# using AM_GLIB_GNU_GETTEXT +AC_PREREQ(2.53) + +dnl +dnl We go to great lengths to make sure that aclocal won't +dnl try to pull in the installed version of these macros +dnl when running aclocal in the glib directory. +dnl +m4_copy([AC_DEFUN],[glib_DEFUN]) +m4_copy([AC_REQUIRE],[glib_REQUIRE]) +dnl +dnl At the end, if we're not within glib, we'll define the public +dnl definitions in terms of our private definitions. +dnl + +# GLIB_LC_MESSAGES +#-------------------- +glib_DEFUN([GLIB_LC_MESSAGES], + [AC_CHECK_HEADERS([locale.h]) + if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your file defines LC_MESSAGES.]) + fi + fi]) + +# GLIB_PATH_PROG_WITH_TEST +#---------------------------- +dnl GLIB_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +glib_DEFUN([GLIB_PATH_PROG_WITH_TEST], +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# GLIB_WITH_NLS +#----------------- +glib_DEFUN([GLIB_WITH_NLS], + dnl NLS is obligatory + [USE_NLS=yes + AC_SUBST(USE_NLS) + + gt_cv_have_gettext=no + + CATOBJEXT=NONE + XGETTEXT=: + INTLLIBS= + + AC_CHECK_HEADER(libintl.h, + [gt_cv_func_dgettext_libintl="no" + libintl_extra_libs="" + + # + # First check in libc + # + AC_CACHE_CHECK([for ngettext in libc], gt_cv_func_ngettext_libc, + [AC_TRY_LINK([ +#include +], + [return !ngettext ("","", 1)], + gt_cv_func_ngettext_libc=yes, + gt_cv_func_ngettext_libc=no) + ]) + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + AC_CACHE_CHECK([for dgettext in libc], gt_cv_func_dgettext_libc, + [AC_TRY_LINK([ +#include +], + [return !dgettext ("","")], + gt_cv_func_dgettext_libc=yes, + gt_cv_func_dgettext_libc=no) + ]) + fi + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + AC_CHECK_FUNCS(bind_textdomain_codeset) + fi + + # + # If we don't have everything we want, check in libintl + # + if test "$gt_cv_func_dgettext_libc" != "yes" \ + || test "$gt_cv_func_ngettext_libc" != "yes" \ + || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then + + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CHECK_LIB(intl, ngettext, + [AC_CHECK_LIB(intl, dgettext, + gt_cv_func_dgettext_libintl=yes)])]) + + if test "$gt_cv_func_dgettext_libintl" != "yes" ; then + AC_MSG_CHECKING([if -liconv is needed to use gettext]) + AC_MSG_RESULT([]) + AC_CHECK_LIB(intl, ngettext, + [AC_CHECK_LIB(intl, dcgettext, + [gt_cv_func_dgettext_libintl=yes + libintl_extra_libs=-liconv], + :,-liconv)], + :,-liconv) + fi + + # + # If we found libintl, then check in it for bind_textdomain_codeset(); + # we'll prefer libc if neither have bind_textdomain_codeset(), + # and both have dgettext and ngettext + # + if test "$gt_cv_func_dgettext_libintl" = "yes" ; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS -lintl $libintl_extra_libs" + unset ac_cv_func_bind_textdomain_codeset + AC_CHECK_FUNCS(bind_textdomain_codeset) + LIBS="$glib_save_LIBS" + + if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then + gt_cv_func_dgettext_libc=no + else + if test "$gt_cv_func_dgettext_libc" = "yes" \ + && test "$gt_cv_func_ngettext_libc" = "yes"; then + gt_cv_func_dgettext_libintl=no + fi + fi + fi + fi + + if test "$gt_cv_func_dgettext_libc" = "yes" \ + || test "$gt_cv_func_dgettext_libintl" = "yes"; then + gt_cv_have_gettext=yes + fi + + if test "$gt_cv_func_dgettext_libintl" = "yes"; then + INTLLIBS="-lintl $libintl_extra_libs" + fi + + if test "$gt_cv_have_gettext" = "yes"; then + AC_DEFINE(HAVE_GETTEXT,1, + [Define if the GNU gettext() function is already present or preinstalled.]) + GLIB_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS $INTLLIBS" + AC_CHECK_FUNCS(dcgettext) + MSGFMT_OPTS= + AC_MSG_CHECKING([if msgfmt accepts -c]) + GLIB_RUN_PROG([$MSGFMT -c -o /dev/null],[ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: test 1.0\n" +"PO-Revision-Date: 2007-02-15 12:01+0100\n" +"Last-Translator: test \n" +"Language-Team: C \n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" +], [MSGFMT_OPTS=-c; AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) + AC_SUBST(MSGFMT_OPTS) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + GLIB_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [case $host in + *-*-solaris*) + dnl On Solaris, if bind_textdomain_codeset is in libc, + dnl GNU format message catalog is always supported, + dnl since both are added to the libc all together. + dnl Hence, we'd like to go with DATADIRNAME=share and + dnl and CATOBJEXT=.gmo in this case. + AC_CHECK_FUNC(bind_textdomain_codeset, + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + ;; + *) + CATOBJEXT=.mo + DATADIRNAME=lib + ;; + esac]) + LIBS="$glib_save_LIBS" + INSTOBJEXT=.mo + else + gt_cv_have_gettext=no + fi + fi + ]) + + if test "$gt_cv_have_gettext" = "yes" ; then + AC_DEFINE(ENABLE_NLS, 1, + [always defined to indicate that i18n is enabled]) + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is not GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + + AC_OUTPUT_COMMANDS( + [case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac]) + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.in. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLLIBS) + AC_SUBST(PO_IN_DATADIR_TRUE) + AC_SUBST(PO_IN_DATADIR_FALSE) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +# AM_GLIB_GNU_GETTEXT +# ------------------- +# Do checks necessary for use of gettext. If a suitable implementation +# of gettext is found in either in libintl or in the C library, +# it will set INTLLIBS to the libraries needed for use of gettext +# and AC_DEFINE() HAVE_GETTEXT and ENABLE_NLS. (The shell variable +# gt_cv_have_gettext will be set to "yes".) It will also call AC_SUBST() +# on various variables needed by the Makefile.in.in installed by +# glib-gettextize. +dnl +glib_DEFUN([GLIB_GNU_GETTEXT], + [AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + + GLIB_LC_MESSAGES + GLIB_WITH_NLS + + if test "$gt_cv_have_gettext" = "yes"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + NEW_LINGUAS="$NEW_LINGUAS $presentlang" + fi + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but ($top_srcdir). + dnl Try to locate is. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + ]) + +# AM_GLIB_DEFINE_LOCALEDIR(VARIABLE) +# ------------------------------- +# Define VARIABLE to the location where catalog files will +# be installed by po/Makefile. +glib_DEFUN([GLIB_DEFINE_LOCALEDIR], +[glib_REQUIRE([GLIB_GNU_GETTEXT])dnl +glib_save_prefix="$prefix" +glib_save_exec_prefix="$exec_prefix" +glib_save_datarootdir="$datarootdir" +test "x$prefix" = xNONE && prefix=$ac_default_prefix +test "x$exec_prefix" = xNONE && exec_prefix=$prefix +datarootdir=`eval echo "${datarootdir}"` +if test "x$CATOBJEXT" = "x.mo" ; then + localedir=`eval echo "${libdir}/locale"` +else + localedir=`eval echo "${datadir}/locale"` +fi +prefix="$glib_save_prefix" +exec_prefix="$glib_save_exec_prefix" +datarootdir="$glib_save_datarootdir" +AC_DEFINE_UNQUOTED($1, "$localedir", + [Define the location where the catalogs will be installed]) +]) + +dnl +dnl Now the definitions that aclocal will find +dnl +ifdef(glib_configure_in,[],[ +AC_DEFUN([AM_GLIB_GNU_GETTEXT],[GLIB_GNU_GETTEXT($@)]) +AC_DEFUN([AM_GLIB_DEFINE_LOCALEDIR],[GLIB_DEFINE_LOCALEDIR($@)]) +])dnl + +# GLIB_RUN_PROG(PROGRAM, TEST-FILE, [ACTION-IF-PASS], [ACTION-IF-FAIL]) +# +# Create a temporary file with TEST-FILE as its contents and pass the +# file name to PROGRAM. Perform ACTION-IF-PASS if PROGRAM exits with +# 0 and perform ACTION-IF-FAIL for any other exit status. +AC_DEFUN([GLIB_RUN_PROG], +[cat >conftest.foo <<_ACEOF +$2 +_ACEOF +if AC_RUN_LOG([$1 conftest.foo]); then + m4_ifval([$3], [$3], [:]) +m4_ifvaln([$4], [else $4])dnl +echo "$as_me: failed input was:" >&AS_MESSAGE_LOG_FD +sed 's/^/| /' conftest.foo >&AS_MESSAGE_LOG_FD +fi]) + diff --git a/common/m4/gst-arch.m4 b/common/m4/gst-arch.m4 new file mode 100644 index 0000000..077a20b --- /dev/null +++ b/common/m4/gst-arch.m4 @@ -0,0 +1,140 @@ +dnl AG_GST_ARCH +dnl sets up defines and automake conditionals for host architecture +dnl checks endianness +dnl defines HOST_CPU + +AC_DEFUN([AG_GST_ARCH], +[ + dnl Determine CPU + case "x${target_cpu}" in + xi?86 | xk? | xi?86_64) + case $target_os in + solaris*) + AC_CHECK_DECL([__i386], [I386_ABI="yes"], [I386_ABI="no"]) + AC_CHECK_DECL([__amd64], [AMD64_ABI="yes"], [AMD64_ABI="no"]) + + if test "x$I386_ABI" = "xyes" ; then + HAVE_CPU_I386=yes + AC_DEFINE(HAVE_CPU_I386, 1, [Define if the target CPU is an x86]) + fi + if test "x$AMD64_ABI" = "xyes" ; then + HAVE_CPU_X86_64=yes + AC_DEFINE(HAVE_CPU_X86_64, 1, [Define if the target CPU is a x86_64]) + fi + ;; + *) + HAVE_CPU_I386=yes + AC_DEFINE(HAVE_CPU_I386, 1, [Define if the target CPU is an x86]) + + dnl FIXME could use some better detection + dnl (ie CPUID) + case "x${target_cpu}" in + xi386 | xi486) ;; + *) + AC_DEFINE(HAVE_RDTSC, 1, [Define if RDTSC is available]) ;; + esac + ;; + esac + ;; + xpowerpc) + HAVE_CPU_PPC=yes + AC_DEFINE(HAVE_CPU_PPC, 1, [Define if the target CPU is a PowerPC]) ;; + xpowerpc64) + HAVE_CPU_PPC64=yes + AC_DEFINE(HAVE_CPU_PPC64, 1, [Define if the target CPU is a 64 bit PowerPC]) ;; + xalpha*) + HAVE_CPU_ALPHA=yes + AC_DEFINE(HAVE_CPU_ALPHA, 1, [Define if the target CPU is an Alpha]) ;; + xarm*) + HAVE_CPU_ARM=yes + AC_DEFINE(HAVE_CPU_ARM, 1, [Define if the target CPU is an ARM]) ;; + xsparc*) + HAVE_CPU_SPARC=yes + AC_DEFINE(HAVE_CPU_SPARC, 1, [Define if the target CPU is a SPARC]) ;; + xmips*) + HAVE_CPU_MIPS=yes + AC_DEFINE(HAVE_CPU_MIPS, 1, [Define if the target CPU is a MIPS]) ;; + xhppa*) + HAVE_CPU_HPPA=yes + AC_DEFINE(HAVE_CPU_HPPA, 1, [Define if the target CPU is a HPPA]) ;; + xs390*) + HAVE_CPU_S390=yes + AC_DEFINE(HAVE_CPU_S390, 1, [Define if the target CPU is a S390]) ;; + xia64*) + HAVE_CPU_IA64=yes + AC_DEFINE(HAVE_CPU_IA64, 1, [Define if the target CPU is a IA64]) ;; + xm68k*) + HAVE_CPU_M68K=yes + AC_DEFINE(HAVE_CPU_M68K, 1, [Define if the target CPU is a M68K]) ;; + xx86_64) + HAVE_CPU_X86_64=yes + AC_DEFINE(HAVE_CPU_X86_64, 1, [Define if the target CPU is a x86_64]) ;; + xcris) + HAVE_CPU_CRIS=yes + AC_DEFINE(HAVE_CPU_CRIS, 1, [Define if the target CPU is a CRIS]) ;; + xcrisv32) + HAVE_CPU_CRISV32=yes + AC_DEFINE(HAVE_CPU_CRISV32, 1, [Define if the target CPU is a CRISv32]) ;; + esac + + dnl Determine endianness + AC_C_BIGENDIAN + + AM_CONDITIONAL(HAVE_CPU_I386, test "x$HAVE_CPU_I386" = "xyes") + AM_CONDITIONAL(HAVE_CPU_PPC, test "x$HAVE_CPU_PPC" = "xyes") + AM_CONDITIONAL(HAVE_CPU_PPC64, test "x$HAVE_CPU_PPC64" = "xyes") + AM_CONDITIONAL(HAVE_CPU_ALPHA, test "x$HAVE_CPU_ALPHA" = "xyes") + AM_CONDITIONAL(HAVE_CPU_ARM, test "x$HAVE_CPU_ARM" = "xyes") + AM_CONDITIONAL(HAVE_CPU_SPARC, test "x$HAVE_CPU_SPARC" = "xyes") + AM_CONDITIONAL(HAVE_CPU_HPPA, test "x$HAVE_CPU_HPPA" = "xyes") + AM_CONDITIONAL(HAVE_CPU_MIPS, test "x$HAVE_CPU_MIPS" = "xyes") + AM_CONDITIONAL(HAVE_CPU_S390, test "x$HAVE_CPU_S390" = "xyes") + AM_CONDITIONAL(HAVE_CPU_IA64, test "x$HAVE_CPU_IA64" = "xyes") + AM_CONDITIONAL(HAVE_CPU_M68K, test "x$HAVE_CPU_M68K" = "xyes") + AM_CONDITIONAL(HAVE_CPU_X86_64, test "x$HAVE_CPU_X86_64" = "xyes") + AM_CONDITIONAL(HAVE_CPU_CRIS, test "x$HAVE_CPU_CRIS" = "xyes") + AM_CONDITIONAL(HAVE_CPU_CRISV32, test "x$HAVE_CPU_CRISV32" = "xyes") + + AC_DEFINE_UNQUOTED(HOST_CPU, "$host_cpu", [the host CPU]) + AC_DEFINE_UNQUOTED(TARGET_CPU, "$target_cpu", [the target CPU]) +]) + +dnl check if unaligned memory access works correctly +AC_DEFUN([AG_GST_UNALIGNED_ACCESS], [ + AC_MSG_CHECKING([if unaligned memory access works correctly]) + if test x"$as_cv_unaligned_access" = x ; then + case $host in + alpha*|arm*|hp*|mips*|sh*|sparc*|ia64*) + _AS_ECHO_N([(blacklisted) ]) + as_cv_unaligned_access=no + ;; + i?86*|x86_64*|amd64*|powerpc*|m68k*|cris*) + _AS_ECHO_N([(whitelisted) ]) + as_cv_unaligned_access=yes + ;; + esac + else + _AS_ECHO_N([(cached) ]) + fi + if test x"$as_cv_unaligned_access" = x ; then + AC_TRY_RUN([ +int main(int argc, char **argv) +{ + char array[] = "ABCDEFGH"; + unsigned int iarray[2]; + memcpy(iarray,array,8); +#define GET(x) (*(unsigned int *)((char *)iarray + (x))) + if(GET(0) != 0x41424344 && GET(0) != 0x44434241) return 1; + if(GET(1) != 0x42434445 && GET(1) != 0x45444342) return 1; + if(GET(2) != 0x43444546 && GET(2) != 0x46454443) return 1; + if(GET(3) != 0x44454647 && GET(3) != 0x47464544) return 1; + return 0; +} + ], as_cv_unaligned_access="yes", as_cv_unaligned_access="no") + fi + AC_MSG_RESULT($as_cv_unaligned_access) + if test "$as_cv_unaligned_access" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_UNALIGNED_ACCESS, 1, + [defined if unaligned memory access works correctly]) + fi +]) diff --git a/common/m4/gst-args.m4 b/common/m4/gst-args.m4 new file mode 100644 index 0000000..b478c82 --- /dev/null +++ b/common/m4/gst-args.m4 @@ -0,0 +1,360 @@ +dnl configure-time options shared among gstreamer modules + +dnl AG_GST_ARG_DEBUG +dnl AG_GST_ARG_PROFILING +dnl AG_GST_ARG_VALGRIND +dnl AG_GST_ARG_GCOV + +dnl AG_GST_ARG_EXAMPLES + +dnl AG_GST_ARG_WITH_PKG_CONFIG_PATH +dnl AG_GST_ARG_WITH_PACKAGE_NAME +dnl AG_GST_ARG_WITH_PACKAGE_ORIGIN + +dnl AG_GST_ARG_WITH_PLUGINS +dnl AG_GST_CHECK_PLUGIN +dnl AG_GST_DISABLE_PLUGIN + +dnl AG_GST_ARG_ENABLE_EXTERNAL +dnl AG_GST_ARG_ENABLE_EXPERIMENTAL +dnl AG_GST_ARG_ENABLE_BROKEN + +dnl AG_GST_ARG_DISABLE_FATAL_WARNINGS +AC_DEFUN([AG_GST_ARG_DEBUG], +[ + dnl debugging stuff + AC_ARG_ENABLE(debug, + AC_HELP_STRING([--disable-debug],[disable addition of -g debugging info]), + [ + case "${enableval}" in + yes) USE_DEBUG=yes ;; + no) USE_DEBUG=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; + esac + ], + [USE_DEBUG=yes]) dnl Default value +]) + +AC_DEFUN([AG_GST_ARG_PROFILING], +[ + AC_ARG_ENABLE(profiling, + AC_HELP_STRING([--enable-profiling], + [adds -pg to compiler commandline, for profiling]), + [ + case "${enableval}" in + yes) USE_PROFILING=yes ;; + no) USE_PROFILING=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-profiling) ;; + esac + ], + [USE_PROFILING=no]) dnl Default value +]) + +AC_DEFUN([AG_GST_ARG_VALGRIND], +[ + dnl valgrind inclusion + AC_ARG_ENABLE(valgrind, + AC_HELP_STRING([--disable-valgrind],[disable run-time valgrind detection]), + [ + case "${enableval}" in + yes) USE_VALGRIND="$USE_DEBUG" ;; + no) USE_VALGRIND=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-valgrind) ;; + esac + ], + [USE_VALGRIND="$USE_DEBUG"]) dnl Default value + VALGRIND_REQ="3.0" + if test "x$USE_VALGRIND" = xyes; then + PKG_CHECK_MODULES(VALGRIND, valgrind >= $VALGRIND_REQ, + USE_VALGRIND="yes", + USE_VALGRIND="no") + fi + if test "x$USE_VALGRIND" = xyes; then + AC_DEFINE(HAVE_VALGRIND, 1, [Define if valgrind should be used]) + AC_MSG_NOTICE(Using extra code paths for valgrind) + fi +]) + +AC_DEFUN([AG_GST_ARG_GCOV], +[ + AC_ARG_ENABLE(gcov, + AC_HELP_STRING([--enable-gcov], + [compile with coverage profiling instrumentation (gcc only)]), + enable_gcov=$enableval, + enable_gcov=no) + if test x$enable_gcov = xyes ; then + if test "x$GCC" != "xyes" + then + AC_MSG_ERROR([gcov only works if gcc is used]) + fi + + AS_COMPILER_FLAG(["-fprofile-arcs"], + [GCOV_CFLAGS="$GCOV_CFLAGS -fprofile-arcs"], + true) + AS_COMPILER_FLAG(["-ftest-coverage"], + [GCOV_CFLAGS="$GCOV_CFLAGS -ftest-coverage"], + true) + dnl remove any -O flags - FIXME: is this needed ? + GCOV_CFLAGS=`echo "$GCOV_CFLAGS" | sed -e 's/-O[[0-9]]*//g'` + dnl libtool 1.5.22 and lower strip -fprofile-arcs from the flags + dnl passed to the linker, which is a bug; -fprofile-arcs implicitly + dnl links in -lgcov, so we do it explicitly here for the same effect + GCOV_LIBS=-lgcov + AC_SUBST(GCOV_CFLAGS) + AC_SUBST(GCOV_LIBS) + GCOV=`echo $CC | sed s/gcc/gcov/g` + AC_SUBST(GCOV) + + GST_GCOV_ENABLED=yes + AC_DEFINE_UNQUOTED(GST_GCOV_ENABLED, 1, + [Defined if gcov is enabled to force a rebuild due to config.h changing]) + dnl if gcov is used, we do not want default -O2 CFLAGS + if test "x$GST_GCOV_ENABLED" = "xyes" + then + CFLAGS="$CFLAGS -O0" + AC_SUBST(CFLAGS) + CXXFLAGS="$CXXFLAGS -O0" + AC_SUBST(CXXFLAGS) + FFLAGS="$FFLAGS -O0" + AC_SUBST(FFLAGS) + CCASFLAGS="$CCASFLAGS -O0" + AC_SUBST(CCASFLAGS) + AC_MSG_NOTICE([gcov enabled, setting CFLAGS and friends to $CFLAGS]) + fi + fi + AM_CONDITIONAL(GST_GCOV_ENABLED, test x$enable_gcov = xyes) +]) + +AC_DEFUN([AG_GST_ARG_EXAMPLES], +[ + AC_ARG_ENABLE(examples, + AC_HELP_STRING([--disable-examples], [disable building examples]), + [ + case "${enableval}" in + yes) BUILD_EXAMPLES=yes ;; + no) BUILD_EXAMPLES=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-examples) ;; + esac + ], + [BUILD_EXAMPLES=yes]) dnl Default value + AM_CONDITIONAL(BUILD_EXAMPLES, test "x$BUILD_EXAMPLES" = "xyes") +]) + +AC_DEFUN([AG_GST_ARG_WITH_PKG_CONFIG_PATH], +[ + dnl possibly modify pkg-config path + AC_ARG_WITH(pkg-config-path, + AC_HELP_STRING([--with-pkg-config-path], + [colon-separated list of pkg-config(1) dirs]), + [ + export PKG_CONFIG_PATH=${withval} + AC_MSG_NOTICE(Set PKG_CONFIG_PATH to $PKG_CONFIG_PATH) + ]) +]) + + +dnl This macro requires that GST_GIT or GST_CVS is set to yes or no (release) +AC_DEFUN([AG_GST_ARG_WITH_PACKAGE_NAME], +[ + dnl package name in plugins + AC_ARG_WITH(package-name, + AC_HELP_STRING([--with-package-name], + [specify package name to use in plugins]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-package-name) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-package-name) ;; + *) GST_PACKAGE_NAME="${withval}" ;; + esac + ], + [ + P=$1 + if test "x$P" = "x" + then + P=$PACKAGE_NAME + fi + + if test "x$PACKAGE_VERSION_NANO" = "x0" + then + GST_PACKAGE_NAME="$P source release" + else + if test "x$PACKAGE_VERSION_NANO" = "x1" + then + GST_PACKAGE_NAME="$P git" + else + GST_PACKAGE_NAME="$P prerelease" + fi + fi + ] + ) + AC_MSG_NOTICE(Using $GST_PACKAGE_NAME as package name) + AC_DEFINE_UNQUOTED(GST_PACKAGE_NAME, "$GST_PACKAGE_NAME", + [package name in plugins]) + AC_SUBST(GST_PACKAGE_NAME) +]) + +AC_DEFUN([AG_GST_ARG_WITH_PACKAGE_ORIGIN], +[ + dnl package origin URL + AC_ARG_WITH(package-origin, + AC_HELP_STRING([--with-package-origin], + [specify package origin URL to use in plugins]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-package-origin) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-package-origin) ;; + *) GST_PACKAGE_ORIGIN="${withval}" ;; + esac + ], + [GST_PACKAGE_ORIGIN="[Unknown package origin]"] dnl Default value + ) + AC_MSG_NOTICE(Using $GST_PACKAGE_ORIGIN as package origin) + AC_DEFINE_UNQUOTED(GST_PACKAGE_ORIGIN, "$GST_PACKAGE_ORIGIN", + [package origin]) + AC_SUBST(GST_PACKAGE_ORIGIN) +]) + +dnl sets WITH_PLUGINS to the list of plug-ins given as an argument +dnl also clears GST_PLUGINS_ALL and GST_PLUGINS_SELECTED +AC_DEFUN([AG_GST_ARG_WITH_PLUGINS], +[ + AC_ARG_WITH(plugins, + AC_HELP_STRING([--with-plugins], + [comma-separated list of dependencyless plug-ins to compile]), + [WITH_PLUGINS=$withval], + [WITH_PLUGINS=]) + + GST_PLUGINS_ALL="" + GST_PLUGINS_SELECTED="" + GST_PLUGINS_NONPORTED="" + + AC_SUBST(GST_PLUGINS_ALL) + AC_SUBST(GST_PLUGINS_SELECTED) + AC_SUBST(GST_PLUGINS_NONPORTED) +]) + +dnl AG_GST_CHECK_PLUGIN(PLUGIN-NAME) +dnl +dnl This macro adds the plug-in to GST_PLUGINS_ALL. Then it +dnl checks if WITH_PLUGINS is empty or the plugin is present in WITH_PLUGINS, +dnl and if so adds it to GST_PLUGINS_SELECTED. Then it checks if the plugin +dnl is present in WITHOUT_PLUGINS (ie. was disabled specifically) and if so +dnl removes it from GST_PLUGINS_SELECTED. +dnl +dnl The macro will call AM_CONDITIONAL(USE_PLUGIN_, ...) to allow +dnl control of what is built in Makefile.ams. +AC_DEFUN([AG_GST_CHECK_PLUGIN], +[ + GST_PLUGINS_ALL="$GST_PLUGINS_ALL [$1]" + + define([pname_def],translit([$1], -a-z, _a-z)) + + AC_ARG_ENABLE([$1], + AC_HELP_STRING([--disable-[$1]], [disable dependency-less $1 plugin]), + [ + case "${enableval}" in + yes) [gst_use_]pname_def=yes ;; + no) [gst_use_]pname_def=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-$1]) ;; + esac + ], + [[gst_use_]pname_def=yes]) dnl Default value + + if test x$[gst_use_]pname_def = xno; then + AC_MSG_NOTICE(disabling dependency-less plugin $1) + WITHOUT_PLUGINS="$WITHOUT_PLUGINS [$1]" + fi + undefine([pname_def]) + + dnl First check inclusion + if [[ -z "$WITH_PLUGINS" ]] || echo " [$WITH_PLUGINS] " | tr , ' ' | grep -i " [$1] " > /dev/null; then + GST_PLUGINS_SELECTED="$GST_PLUGINS_SELECTED [$1]" + fi + dnl Then check exclusion + if echo " [$WITHOUT_PLUGINS] " | tr , ' ' | grep -i " [$1] " > /dev/null; then + GST_PLUGINS_SELECTED=`echo " $GST_PLUGINS_SELECTED " | $SED -e 's/ [$1] / /'` + fi + dnl Finally check if the plugin is ported or not + if echo " [$GST_PLUGINS_NONPORTED] " | tr , ' ' | grep -i " [$1] " > /dev/null; then + GST_PLUGINS_SELECTED=`echo " $GST_PLUGINS_SELECTED " | $SED -e 's/ [$1] / /'` + fi + AM_CONDITIONAL([USE_PLUGIN_]translit([$1], a-z, A-Z), echo " $GST_PLUGINS_SELECTED " | grep -i " [$1] " > /dev/null) +]) + +dnl AG_GST_DISABLE_PLUGIN(PLUGIN-NAME) +dnl +dnl This macro disables the plug-in by removing it from +dnl GST_PLUGINS_SELECTED. +AC_DEFUN([AG_GST_DISABLE_PLUGIN], +[ + GST_PLUGINS_SELECTED=`echo " $GST_PLUGINS_SELECTED " | $SED -e 's/ [$1] / /'` + AM_CONDITIONAL([USE_PLUGIN_]translit([$1], a-z, A-Z), false) +]) + +AC_DEFUN([AG_GST_ARG_ENABLE_EXTERNAL], +[ + AG_GST_CHECK_FEATURE(EXTERNAL, [building of plug-ins with external deps],, + HAVE_EXTERNAL=yes, enabled, + [ + AC_MSG_NOTICE(building external plug-ins) + BUILD_EXTERNAL="yes" + ],[ + AC_MSG_WARN(all plug-ins with external dependencies will not be built) + BUILD_EXTERNAL="no" + ]) + # make BUILD_EXTERNAL available to Makefile.am + AM_CONDITIONAL(BUILD_EXTERNAL, test "x$BUILD_EXTERNAL" = "xyes") +]) + +dnl experimental plug-ins; stuff that hasn't had the dust settle yet +dnl read 'builds, but might not work' +AC_DEFUN([AG_GST_ARG_ENABLE_EXPERIMENTAL], +[ + AG_GST_CHECK_FEATURE(EXPERIMENTAL, [building of experimental plug-ins],, + HAVE_EXPERIMENTAL=yes, disabled, + [ + AC_MSG_WARN(building experimental plug-ins) + BUILD_EXPERIMENTAL="yes" + ],[ + AC_MSG_NOTICE(not building experimental plug-ins) + BUILD_EXPERIMENTAL="no" + ]) + # make BUILD_EXPERIMENTAL available to Makefile.am + AM_CONDITIONAL(BUILD_EXPERIMENTAL, test "x$BUILD_EXPERIMENTAL" = "xyes") +]) + +dnl broken plug-ins; stuff that doesn't seem to build at the moment +AC_DEFUN([AG_GST_ARG_ENABLE_BROKEN], +[ + AG_GST_CHECK_FEATURE(BROKEN, [building of broken plug-ins],, + HAVE_BROKEN=yes, disabled, + [ + AC_MSG_WARN([building broken plug-ins -- no bug reports on these, only patches ...]) + ],[ + AC_MSG_NOTICE([not building broken plug-ins]) + ]) +]) + +dnl allow people (or build tools) to override default behaviour +dnl for fatal compiler warnings +dnl Enable fatal warnings by default only for development versions +AC_DEFUN([AG_GST_ARG_DISABLE_FATAL_WARNINGS], +[ + AC_ARG_ENABLE(fatal-warnings, + AC_HELP_STRING([--disable-fatal-warnings], + [Don't turn compiler warnings into fatal errors]), + [ + case "${enableval}" in + yes) FATAL_WARNINGS=yes ;; + no) FATAL_WARNINGS=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-fatal-warnings) ;; + esac + ], + [ + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then + FATAL_WARNINGS=yes + else + FATAL_WARNINGS=no + fi + ]) +]) diff --git a/common/m4/gst-check.m4 b/common/m4/gst-check.m4 new file mode 100644 index 0000000..4277053 --- /dev/null +++ b/common/m4/gst-check.m4 @@ -0,0 +1,294 @@ +dnl pkg-config-based checks for GStreamer modules and dependency modules + +dnl generic: +dnl AG_GST_PKG_CHECK_MODULES([PREFIX], [WHICH], [REQUIRED]) +dnl sets HAVE_[$PREFIX], [$PREFIX]_* +dnl AG_GST_CHECK_MODULES([PREFIX], [MODULE], [MINVER], [NAME], [REQUIRED]) +dnl sets HAVE_[$PREFIX], [$PREFIX]_* + +dnl specific: +dnl AG_GST_CHECK_GST([MAJMIN], [MINVER], [REQUIRED]) +dnl also sets/ACSUBSTs GST_TOOLS_DIR and GST_PLUGINS_DIR +dnl AG_GST_CHECK_GST_BASE([MAJMIN], [MINVER], [REQUIRED]) +dnl AG_GST_CHECK_GST_CONTROLLER([MAJMIN], [MINVER], [REQUIRED]) +dnl AG_GST_CHECK_GST_NET([MAJMIN], [MINVER], [REQUIRED]) +dnl AG_GST_CHECK_GST_CHECK([MAJMIN], [MINVER], [REQUIRED]) +dnl AG_GST_CHECK_GST_PLUGINS_BASE([MAJMIN], [MINVER], [REQUIRED]) +dnl also sets/ACSUBSTs GSTPB_PLUGINS_DIR + +AC_DEFUN([AG_GST_PKG_CHECK_MODULES], +[ + which="[$2]" + dnl not required by default, since we use this mostly for plugin deps + required=ifelse([$3], , "no", [$3]) + + PKG_CHECK_MODULES([$1], $which, + [ + HAVE_[$1]="yes" + ], + [ + HAVE_[$1]="no" + if test "x$required" = "xyes"; then + AC_MSG_ERROR($[$1]_PKG_ERRORS) + else + AC_MSG_NOTICE($[$1]_PKG_ERRORS) + fi + ]) + + dnl AC_SUBST of CFLAGS and LIBS was not done before automake 1.7 + dnl It gets done automatically in automake >= 1.7, which we now require +])) + +AC_DEFUN([AG_GST_CHECK_MODULES], +[ + module=[$2] + minver=[$3] + name="[$4]" + required=ifelse([$5], , "yes", [$5]) dnl required by default + + PKG_CHECK_MODULES([$1], $module >= $minver, + [ + HAVE_[$1]="yes" + ], + [ + HAVE_[$1]="no" + AC_MSG_NOTICE($[$1]_PKG_ERRORS) + if test "x$required" = "xyes"; then + AC_MSG_ERROR([no $module >= $minver ($name) found]) + else + AC_MSG_NOTICE([no $module >= $minver ($name) found]) + fi + ]) + + dnl AC_SUBST of CFLAGS and LIBS was not done before automake 1.7 + dnl It gets done automatically in automake >= 1.7, which we now require +])) + +AC_DEFUN([AG_GST_CHECK_GST], +[ + AG_GST_CHECK_MODULES(GST, gstreamer-[$1], [$2], [GStreamer], [$3]) + dnl allow setting before calling this macro to override + if test -z $GST_TOOLS_DIR; then + GST_TOOLS_DIR=`$PKG_CONFIG --variable=toolsdir gstreamer-[$1]` + if test -z $GST_TOOLS_DIR; then + AC_MSG_ERROR( + [no tools dir set in GStreamer pkg-config file, core upgrade needed.]) + fi + fi + AC_MSG_NOTICE([using GStreamer tools in $GST_TOOLS_DIR]) + AC_SUBST(GST_TOOLS_DIR) + + dnl check for where core plug-ins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GST_PLUGINS_DIR; then + GST_PLUGINS_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-[$1]` + if test -z $GST_PLUGINS_DIR; then + AC_MSG_ERROR( + [no pluginsdir set in GStreamer pkg-config file, core upgrade needed.]) + fi + fi + AC_MSG_NOTICE([using GStreamer plug-ins in $GST_PLUGINS_DIR]) + AC_SUBST(GST_PLUGINS_DIR) +]) + +AC_DEFUN([AG_GST_CHECK_GST_BASE], +[ + AG_GST_CHECK_MODULES(GST_BASE, gstreamer-base-[$1], [$2], + [GStreamer Base Libraries], [$3]) +]) + +AC_DEFUN([AG_GST_CHECK_GST_CONTROLLER], +[ + AG_GST_CHECK_MODULES(GST_CONTROLLER, gstreamer-controller-[$1], [$2], + [GStreamer Controller Library], [$3]) +]) + +AC_DEFUN([AG_GST_CHECK_GST_NET], +[ + AG_GST_CHECK_MODULES(GST_NET, gstreamer-net-[$1], [$2], + [GStreamer Network Library], [$3]) +]) + +AC_DEFUN([AG_GST_CHECK_GST_CHECK], +[ + AG_GST_CHECK_MODULES(GST_CHECK, gstreamer-check-[$1], [$2], + [GStreamer Check unittest Library], [$3]) +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_UNINSTALLED_SETUP([ACTION-IF-UNINSTALLED], [ACTION-IF-NOT]) +dnl +dnl ACTION-IF-UNINSTALLED (optional) extra actions to perform if the setup +dnl is an uninstalled setup +dnl ACTION-IF-NOT (optional) extra actions to perform if the setup +dnl is not an uninstalled setup +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_UNINSTALLED_SETUP], +[ + AC_MSG_CHECKING([whether this is an uninstalled GStreamer setup]) + AC_CACHE_VAL(gst_cv_is_uninstalled_setup,[ + gst_cv_is_uninstalled_setup=no + if (set -u; : $GST_PLUGIN_SYSTEM_PATH) 2>/dev/null ; then + if test -z "$GST_PLUGIN_SYSTEM_PATH" \ + -a -n "$GST_PLUGIN_SCANNER" \ + -a -n "$GST_PLUGIN_PATH" \ + -a -n "$GST_REGISTRY" \ + -a -n "$DYLD_LIBRARY_PATH" \ + -a -n "$LD_LIBRARY_PATH"; then + gst_cv_is_uninstalled_setup=yes; + fi + fi + ]) + AC_MSG_RESULT($gst_cv_is_uninstalled_setup) + if test "x$gst_cv_is_uninstalled_setup" = "xyes"; then + ifelse([$1], , :, [$1]) + else + ifelse([$2], , :, [$2]) + fi +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_GST_PLUGINS_BASE([GST-API_VERSION], [MIN-VERSION], [REQUIRED]) +dnl +dnl Sets GST_PLUGINS_BASE_CFLAGS and GST_PLUGINS_BASE_LIBS. +dnl +dnl Also sets GSTPB_PLUGINS_DIR (and for consistency also GST_PLUGINS_BASE_DIR) +dnl for use in Makefile.am. This is only really needed/useful in uninstalled +dnl setups, since in an installed setup all plugins will be found in +dnl GST_PLUGINS_DIR anyway. +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_BASE], +[ + AG_GST_CHECK_MODULES(GST_PLUGINS_BASE, gstreamer-plugins-base-[$1], [$2], + [GStreamer Base Plugins], [$3]) + + if test "x$HAVE_GST_PLUGINS_BASE" = "xyes"; then + dnl check for where base plugins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GSTPB_PLUGINS_DIR; then + GSTPB_PLUGINS_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-base-[$1]` + if test -z $GSTPB_PLUGINS_DIR; then + AC_MSG_ERROR( + [no pluginsdir set in GStreamer Base Plugins pkg-config file]) + fi + fi + AC_MSG_NOTICE([using GStreamer Base Plugins in $GSTPB_PLUGINS_DIR]) + GST_PLUGINS_BASE_DIR="$GSTPB_PLUGINS_DIR/gst:$GSTPB_PLUGINS_DIR/sys:$GSTPB_PLUGINS_DIR/ext" + AC_SUBST(GST_PLUGINS_BASE_DIR) + AC_SUBST(GSTPB_PLUGINS_DIR) + fi +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_GST_PLUGINS_GOOD([GST-API_VERSION], [MIN-VERSION]) +dnl +dnl Will set GST_PLUGINS_GOOD_DIR for use in Makefile.am. Note that this will +dnl only be set in an uninstalled setup, since -good ships no .pc file and in +dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway. +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_GOOD], +[ + AG_GST_CHECK_MODULES(GST_PLUGINS_GOOD, gstreamer-plugins-good-[$1], [$2], + [GStreamer Good Plugins], [no]) + + if test "x$HAVE_GST_PLUGINS_GOOD" = "xyes"; then + dnl check for where good plugins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GST_PLUGINS_GOOD_DIR; then + GST_PLUGINS_GOOD_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-good-[$1]` + if test -z $GST_PLUGINS_GOOD_DIR; then + AC_MSG_ERROR([no pluginsdir set in GStreamer Good Plugins pkg-config file]) + fi + fi + AC_MSG_NOTICE([using GStreamer Good Plugins in $GST_PLUGINS_GOOD_DIR]) + GST_PLUGINS_GOOD_DIR="$GST_PLUGINS_GOOD_DIR/gst:$GST_PLUGINS_GOOD_DIR/sys:$GST_PLUGINS_GOOD_DIR/ext" + AC_SUBST(GST_PLUGINS_GOOD_DIR) + fi +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_GST_PLUGINS_UGLY([GST-API_VERSION], [MIN-VERSION]) +dnl +dnl Will set GST_PLUGINS_UGLY_DIR for use in Makefile.am. Note that this will +dnl only be set in an uninstalled setup, since -bad ships no .pc file and in +dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway. +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_UGLY], +[ + AG_GST_CHECK_MODULES(GST_PLUGINS_UGLY, gstreamer-plugins-ugly-[$1], [$2], + [GStreamer Ugly Plugins], [no]) + + if test "x$HAVE_GST_PLUGINS_UGLY" = "xyes"; then + dnl check for where ugly plugins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GST_PLUGINS_UGLY_DIR; then + GST_PLUGINS_UGLY_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-ugly-[$1]` + if test -z $GST_PLUGINS_UGLY_DIR; then + AC_MSG_ERROR([no pluginsdir set in GStreamer Ugly Plugins pkg-config file]) + fi + fi + AC_MSG_NOTICE([using GStreamer Ugly Plugins in $GST_PLUGINS_UGLY_DIR]) + GST_PLUGINS_UGLY_DIR="$GST_PLUGINS_UGLY_DIR/gst:$GST_PLUGINS_UGLY_DIR/sys:$GST_PLUGINS_UGLY_DIR/ext" + AC_SUBST(GST_PLUGINS_UGLY_DIR) + fi +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_GST_PLUGINS_BAD([GST-API_VERSION], [MIN-VERSION]) +dnl +dnl Will set GST_PLUGINS_BAD_DIR for use in Makefile.am. Note that this will +dnl only be set in an uninstalled setup, since -ugly ships no .pc file and in +dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway. +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_BAD], +[ + AG_GST_CHECK_MODULES(GST_PLUGINS_BAD, gstreamer-plugins-bad-[$1], [$2], + [GStreamer Bad Plugins], [no]) + + if test "x$HAVE_GST_PLUGINS_BAD" = "xyes"; then + dnl check for where bad plugins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GST_PLUGINS_BAD_DIR; then + GST_PLUGINS_BAD_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-bad-[$1]` + if test -z $GST_PLUGINS_BAD_DIR; then + AC_MSG_ERROR([no pluginsdir set in GStreamer Bad Plugins pkg-config file]) + fi + fi + AC_MSG_NOTICE([using GStreamer Bad Plugins in $GST_PLUGINS_BAD_DIR]) + GST_PLUGINS_BAD_DIR="$GST_PLUGINS_BAD_DIR/gst:$GST_PLUGINS_BAD_DIR/sys:$GST_PLUGINS_BAD_DIR/ext" + AC_SUBST(GST_PLUGINS_BAD_DIR) + fi +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_GST_PLUGINS_LIBAV([GST-API_VERSION], [MIN-VERSION]) +dnl +dnl Will set GST_PLUGINS_LIBAV_DIR for use in Makefile.am. Note that this will +dnl only be set in an uninstalled setup, since -libav ships no .pc file and in +dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway. +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_LIBAV], +[ + AG_GST_CHECK_MODULES(GST_PLUGINS_LIBAV, gstreamer-plugins-libav-[$1], [$2], + [GStreamer Libav Plugins], [no]) + + if test "x$HAVE_GST_PLUGINS_LIBAV" = "xyes"; then + dnl check for where libav plugins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GST_PLUGINS_LIBAV_DIR; then + GST_PLUGINS_LIBAV_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-libav-[$1]` + if test -z $GST_PLUGINS_LIBAV_DIR; then + AC_MSG_ERROR([no pluginsdir set in GStreamer Libav Plugins pkg-config file]) + fi + fi + GST_PLUGINS_LIBAV_DIR="$GST_PLUGINS_LIBAV_DIR/ext/libav" + AC_MSG_NOTICE([using GStreamer Libav Plugins in $GST_PLUGINS_LIBAV_DIR]) + AC_SUBST(GST_PLUGINS_LIBAV_DIR) + fi +]) diff --git a/common/m4/gst-debuginfo.m4 b/common/m4/gst-debuginfo.m4 new file mode 100644 index 0000000..b48854d --- /dev/null +++ b/common/m4/gst-debuginfo.m4 @@ -0,0 +1,46 @@ +AC_DEFUN([AG_GST_DEBUGINFO], [ +AC_ARG_ENABLE(debug, +AC_HELP_STRING([--disable-debug],[disable addition of -g debugging info]), +[case "${enableval}" in + yes) USE_DEBUG=yes ;; + no) USE_DEBUG=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; +esac], +[USE_DEBUG=yes]) dnl Default value + +AC_ARG_ENABLE(DEBUG, +AC_HELP_STRING([--disable-DEBUG],[disables compilation of debugging messages]), +[case "${enableval}" in + yes) ENABLE_DEBUG=yes ;; + no) ENABLE_DEBUG=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-DEBUG) ;; +esac], +[ENABLE_DEBUG=yes]) dnl Default value +if test x$ENABLE_DEBUG = xyes; then + AC_DEFINE(GST_DEBUG_ENABLED, 1, [Define if DEBUG statements should be compiled in]) +fi + +AC_ARG_ENABLE(INFO, +AC_HELP_STRING([--disable-INFO],[disables compilation of informational messages]), +[case "${enableval}" in + yes) ENABLE_INFO=yes ;; + no) ENABLE_INFO=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-INFO) ;; +esac], +[ENABLE_INFO=yes]) dnl Default value +if test x$ENABLE_INFO = xyes; then + AC_DEFINE(GST_INFO_ENABLED, 1, [Define if INFO statements should be compiled in]) +fi + +AC_ARG_ENABLE(debug-color, +AC_HELP_STRING([--disable-debug-color],[disables color output of DEBUG and INFO output]), +[case "${enableval}" in + yes) ENABLE_DEBUG_COLOR=yes ;; + no) ENABLE_DEBUG_COLOR=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug-color) ;; +esac], +[ENABLE_DEBUG_COLOR=yes]) dnl Default value +if test "x$ENABLE_DEBUG_COLOR" = xyes; then + AC_DEFINE(GST_DEBUG_COLOR, 1, [Define if debugging messages should be colorized]) +fi +]) diff --git a/common/m4/gst-default.m4 b/common/m4/gst-default.m4 new file mode 100644 index 0000000..8de9756 --- /dev/null +++ b/common/m4/gst-default.m4 @@ -0,0 +1,120 @@ +dnl default elements used for tests and such + +dnl AG_GST_DEFAULT_ELEMENTS + +AC_DEFUN([AG_GST_DEFAULT_ELEMENTS], +[ + dnl decide on default elements + dnl FIXME: describe where exactly this gets used + dnl FIXME: decide if it's a problem that this could point to sinks from + dnl depending plugin modules + dnl FIXME: when can we just use autoaudiosrc and autovideosrc? + DEFAULT_AUDIOSINK="autoaudiosink" + DEFAULT_VIDEOSINK="autovideosink" + DEFAULT_AUDIOSRC="alsasrc" + DEFAULT_VIDEOSRC="v4l2src" + DEFAULT_VISUALIZER="goom" + case "$host" in + *-sun-* | *pc-solaris* ) + DEFAULT_AUDIOSRC="sunaudiosrc" + ;; + *-darwin* ) + DEFAULT_AUDIOSRC="osxaudiosrc" + ;; + esac + + dnl Default audio sink + AC_ARG_WITH(default-audiosink, + AC_HELP_STRING([--with-default-audiosink], [specify default audio sink]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-default-audiosink) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-default-audiosink) ;; + *) DEFAULT_AUDIOSINK="${withval}" ;; + esac + ], + [ + DEFAULT_AUDIOSINK="$DEFAULT_AUDIOSINK" + ] dnl Default value as determined above + ) + AC_MSG_NOTICE(Using $DEFAULT_AUDIOSINK as default audio sink) + AC_SUBST(DEFAULT_AUDIOSINK) + AC_DEFINE_UNQUOTED(DEFAULT_AUDIOSINK, "$DEFAULT_AUDIOSINK", + [Default audio sink]) + + dnl Default audio source + AC_ARG_WITH(default-audiosrc, + AC_HELP_STRING([--with-default-audiosrc], [specify default audio source]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-default-audiosrc) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-default-audiosrc) ;; + *) DEFAULT_AUDIOSRC="${withval}" ;; + esac + ], + [ + DEFAULT_AUDIOSRC="$DEFAULT_AUDIOSRC" + ] dnl Default value as determined above + ) + AC_MSG_NOTICE(Using $DEFAULT_AUDIOSRC as default audio source) + AC_SUBST(DEFAULT_AUDIOSRC) + AC_DEFINE_UNQUOTED(DEFAULT_AUDIOSRC, "$DEFAULT_AUDIOSRC", + [Default audio source]) + + dnl Default video sink + AC_ARG_WITH(default-videosink, + AC_HELP_STRING([--with-default-videosink], [specify default video sink]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-default-videosink) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-default-videosink) ;; + *) DEFAULT_VIDEOSINK="${withval}" ;; + esac + ], + [ + DEFAULT_VIDEOSINK="$DEFAULT_VIDEOSINK" + ] dnl Default value as determined above + ) + AC_MSG_NOTICE(Using $DEFAULT_VIDEOSINK as default video sink) + AC_SUBST(DEFAULT_VIDEOSINK) + AC_DEFINE_UNQUOTED(DEFAULT_VIDEOSINK, "$DEFAULT_VIDEOSINK", + [Default video sink]) + + dnl Default video source + AC_ARG_WITH(default-videosrc, + AC_HELP_STRING([--with-default-videosrc], [specify default video source]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-default-videosrc) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-default-videosrc) ;; + *) DEFAULT_VIDEOSRC="${withval}" ;; + esac + ], + [ + DEFAULT_VIDEOSRC="$DEFAULT_VIDEOSRC" + ] dnl Default value as determined above + ) + AC_MSG_NOTICE(Using $DEFAULT_VIDEOSRC as default video source) + AC_SUBST(DEFAULT_VIDEOSRC) + AC_DEFINE_UNQUOTED(DEFAULT_VIDEOSRC, "$DEFAULT_VIDEOSRC", + [Default video source]) + + dnl Default visualizer + AC_ARG_WITH(default-visualizer, + AC_HELP_STRING([--with-default-visualizer], [specify default visualizer]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-default-visualizer) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-default-visualizer) ;; + *) DEFAULT_VISUALIZER="${withval}" ;; + esac + ], + [ + DEFAULT_VISUALIZER="$DEFAULT_VISUALIZER" + ] dnl Default value as determined above + ) + AC_MSG_NOTICE(Using $DEFAULT_VISUALIZER as default visualizer) + AC_SUBST(DEFAULT_VISUALIZER) + AC_DEFINE_UNQUOTED(DEFAULT_VISUALIZER, "$DEFAULT_VISUALIZER", + [Default visualizer]) +]) diff --git a/common/m4/gst-doc.m4 b/common/m4/gst-doc.m4 new file mode 100644 index 0000000..5d3f0fd --- /dev/null +++ b/common/m4/gst-doc.m4 @@ -0,0 +1,92 @@ +AC_DEFUN([AG_GST_DOCBOOK_CHECK], +[ + dnl choose a location to install docbook docs in + if test "x$PACKAGE_TARNAME" = "x" + then + AC_MSG_ERROR([Internal error - PACKAGE_TARNAME not set]) + fi + docdir="\$(datadir)/doc/$PACKAGE_TARNAME-$GST_API_VERSION" + + dnl enable/disable docbook documentation building + AC_ARG_ENABLE(docbook, + AC_HELP_STRING([--enable-docbook], + [use docbook to build documentation [default=no]]),, + enable_docbook=no) + + have_docbook=no + + if test x$enable_docbook = xyes; then + dnl check if we actually have everything we need + + dnl check for docbook tools + AC_CHECK_PROG(HAVE_DOCBOOK2PS, docbook2ps, yes, no) + AC_CHECK_PROG(HAVE_XSLTPROC, xsltproc, yes, no) + AC_CHECK_PROG(HAVE_JADETEX, jadetex, yes, no) + AC_CHECK_PROG(HAVE_PS2PDF, ps2pdf, yes, no) + + dnl check if we can process docbook stuff + AS_DOCBOOK(have_docbook=yes, have_docbook=no) + + dnl check for extra tools + AC_CHECK_PROG(HAVE_DVIPS, dvips, yes, no) + AC_CHECK_PROG(HAVE_XMLLINT, xmllint, yes, no) + + AC_CHECK_PROG(HAVE_PNGTOPNM, pngtopnm, yes, no) + AC_CHECK_PROG(HAVE_PNMTOPS, pnmtops, yes, no) + AC_CHECK_PROG(HAVE_EPSTOPDF, epstopdf, yes, no) + + dnl check if we can generate HTML + if test "x$HAVE_XSLTPROC" = "xyes" && \ + test "x$enable_docbook" = "xyes" && \ + test "x$HAVE_XMLLINT" = "xyes"; then + DOC_HTML=yes + AC_MSG_NOTICE(Will output HTML documentation) + else + DOC_HTML=no + AC_MSG_NOTICE(Will not output HTML documentation) + fi + + dnl check if we can generate PS + if test "x$HAVE_DOCBOOK2PS" = "xyes" && \ + test "x$enable_docbook" = "xyes" && \ + test "x$HAVE_XMLLINT" = "xyes" && \ + test "x$HAVE_JADETEX" = "xyes" && \ + test "x$HAVE_DVIPS" = "xyes" && \ + test "x$HAVE_PNGTOPNM" = "xyes" && \ + test "x$HAVE_PNMTOPS" = "xyes"; then + DOC_PS=yes + AC_MSG_NOTICE(Will output PS documentation) + else + DOC_PS=no + AC_MSG_NOTICE(Will not output PS documentation) + fi + + dnl check if we can generate PDF - using only ps2pdf + if test "x$DOC_PS" = "xyes" && \ + test "x$enable_docbook" = "xyes" && \ + test "x$HAVE_XMLLINT" = "xyes" && \ + test "x$HAVE_PS2PDF" = "xyes"; then + DOC_PDF=yes + AC_MSG_NOTICE(Will output PDF documentation) + else + DOC_PDF=no + AC_MSG_NOTICE(Will not output PDF documentation) + fi + + dnl if we don't have everything, we should disable + if test "x$have_docbook" != "xyes"; then + enable_docbook=no + fi + fi + + dnl if we're going to install documentation, tell us where + if test "x$have_docbook" = "xyes"; then + AC_MSG_NOTICE(Installing documentation in $docdir) + AC_SUBST(docdir) + fi + + AM_CONDITIONAL(ENABLE_DOCBOOK, test x$enable_docbook = xyes) + AM_CONDITIONAL(DOC_HTML, test x$DOC_HTML = xyes) + AM_CONDITIONAL(DOC_PDF, test x$DOC_PDF = xyes) + AM_CONDITIONAL(DOC_PS, test x$DOC_PS = xyes) +]) diff --git a/common/m4/gst-dowhile.m4 b/common/m4/gst-dowhile.m4 new file mode 100644 index 0000000..069808d --- /dev/null +++ b/common/m4/gst-dowhile.m4 @@ -0,0 +1,24 @@ +dnl +dnl Check for working do while(0) macros. This is used by G_STMT_START +dnl and G_STMT_END in glib/gmacros.h. Without having this defined we +dnl get "ambigious if-else" compiler warnings when compling C++ code. +dnl +dnl Copied from GLib's configure.in +dnl +AC_DEFUN([AG_GST_CHECK_DOWHILE_MACROS],[ + +dnl *** check for working do while(0) macros *** +AC_CACHE_CHECK([for working do while(0) macros], _cv_g_support_dowhile_macros, [ + AC_TRY_COMPILE([],[ + #define STMT_START do + #define STMT_END while(0) + #define STMT_TEST STMT_START { i = 0; } STMT_END + int main(void) { int i = 1; STMT_TEST; return i; }], + [_cv_g_support_dowhile_macros=yes], + [_cv_g_support_dowhile_macros=no], + [_cv_g_support_dowhile_macros=yes]) +]) +if test x$_cv_g_support_dowhile_macros = xyes; then + AC_DEFINE(HAVE_DOWHILE_MACROS, 1, [define for working do while(0) macros]) +fi +]) diff --git a/common/m4/gst-error.m4 b/common/m4/gst-error.m4 new file mode 100644 index 0000000..bce80d2 --- /dev/null +++ b/common/m4/gst-error.m4 @@ -0,0 +1,298 @@ +dnl handle various error-related things + +dnl Thomas Vander Stichele +dnl Tim-Philipp Müller + +dnl Last modification: 2008-02-18 + +dnl AG_GST_SET_ERROR_CFLAGS([ADD-WERROR], [MORE_FLAGS]) +dnl AG_GST_SET_ERROR_CXXFLAGS([ADD-WERROR], [MORE_FLAGS]) +dnl AG_GST_SET_LEVEL_DEFAULT([IS-GIT-VERSION]) + + +dnl Sets WARNING_CFLAGS and ERROR_CFLAGS to something the compiler +dnl will accept and AC_SUBST them so they are available in Makefile +dnl +dnl WARNING_CFLAGS will contain flags to make the compiler emit more +dnl warnings. +dnl ERROR_CFLAGS will contain flags to make those warnings fatal, +dnl unless ADD-WERROR is set to "no" +dnl +dnl If MORE_FLAGS is set, tries to add each of the given flags +dnl to WARNING_CFLAGS if the compiler supports them. Each flag is +dnl tested separately. +dnl +dnl These flags can be overridden at make time: +dnl make ERROR_CFLAGS= +AC_DEFUN([AG_GST_SET_ERROR_CFLAGS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AS_COMPILER_FLAG]) + + WARNING_CFLAGS="" + ERROR_CFLAGS="" + + dnl if we support -Wall, set it unconditionally + AS_COMPILER_FLAG(-Wall, + WARNING_CFLAGS="$WARNING_CFLAGS -Wall") + + dnl Warn if declarations after statements are used (C99 extension) + AS_COMPILER_FLAG(-Wdeclaration-after-statement, + WARNING_CFLAGS="$WARNING_CFLAGS -Wdeclaration-after-statement") + + dnl Warn if variable length arrays are used (C99 extension) + AS_COMPILER_FLAG(-Wvla, + WARNING_CFLAGS="$WARNING_CFLAGS -Wvla") + + dnl Warn for invalid pointer arithmetic + AS_COMPILER_FLAG(-Wpointer-arith, + WARNING_CFLAGS="$WARNING_CFLAGS -Wpointer-arith") + + dnl if asked for, add -Werror if supported + if test "x$1" != "xno" + then + AS_COMPILER_FLAG(-Werror, ERROR_CFLAGS="$ERROR_CFLAGS -Werror") + + dnl if -Werror isn't suported, try -errwarn=%all (Sun Forte case) + if test "x$ERROR_CFLAGS" = "x" + then + AS_COMPILER_FLAG([-errwarn=%all], [ + ERROR_CFLAGS="-errwarn=%all" + dnl try -errwarn=%all,no%E_EMPTY_DECLARATION, + dnl no%E_STATEMENT_NOT_REACHED,no%E_ARGUEMENT_MISMATCH, + dnl no%E_MACRO_REDEFINED (Sun Forte case) + dnl For Forte we need disable "empty declaration" warning produced by un-needed semicolon + dnl "statement not reached" disabled because there is g_assert_not_reached () in some places + dnl "macro redefined" because of gst/gettext.h + dnl FIXME: is it really supposed to be 'ARGUEMENT' and not 'ARGUMENT'? + for f in 'no%E_EMPTY_DECLARATION' \ + 'no%E_STATEMENT_NOT_REACHED' \ + 'no%E_ARGUEMENT_MISMATCH' \ + 'no%E_MACRO_REDEFINED' \ + 'no%E_LOOP_NOT_ENTERED_AT_TOP' + do + AS_COMPILER_FLAG([-errwarn=%all,$f], [ + ERROR_CFLAGS="$ERROR_CFLAGS,$f" + ]) + done + ]) + else + dnl Add -fno-strict-aliasing for GLib versions before 2.19.8 + dnl as before G_LOCK and friends caused strict aliasing compiler + dnl warnings. + PKG_CHECK_EXISTS([glib-2.0 < 2.19.8], [ + AS_COMPILER_FLAG(-fno-strict-aliasing, + ERROR_CFLAGS="$ERROR_CFLAGS -fno-strict-aliasing") + ]) + fi + fi + + if test "x$2" != "x" + then + UNSUPPORTED="" + list="$2" + for each in $list + do + AS_COMPILER_FLAG($each, + WARNING_CFLAGS="$WARNING_CFLAGS $each", + UNSUPPORTED="$UNSUPPORTED $each") + done + if test "X$UNSUPPORTED" != X ; then + AC_MSG_NOTICE([unsupported compiler flags: $UNSUPPORTED]) + fi + fi + + AC_SUBST(WARNING_CFLAGS) + AC_SUBST(ERROR_CFLAGS) + AC_MSG_NOTICE([set WARNING_CFLAGS to $WARNING_CFLAGS]) + AC_MSG_NOTICE([set ERROR_CFLAGS to $ERROR_CFLAGS]) +]) + +dnl Sets WARNING_CXXFLAGS and ERROR_CXXFLAGS to something the compiler +dnl will accept and AC_SUBST them so they are available in Makefile +dnl +dnl WARNING_CXXFLAGS will contain flags to make the compiler emit more +dnl warnings. +dnl ERROR_CXXFLAGS will contain flags to make those warnings fatal, +dnl unless ADD-WERROR is set to "no" +dnl +dnl If MORE_FLAGS is set, tries to add each of the given flags +dnl to WARNING_CFLAGS if the compiler supports them. Each flag is +dnl tested separately. +dnl +dnl These flags can be overridden at make time: +dnl make ERROR_CXXFLAGS= +AC_DEFUN([AG_GST_SET_ERROR_CXXFLAGS], +[ + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([AS_CXX_COMPILER_FLAG]) + + ERROR_CXXFLAGS="" + WARNING_CXXFLAGS="" + + dnl if we support -Wall, set it unconditionally + AS_CXX_COMPILER_FLAG(-Wall, WARNING_CXXFLAGS="$WARNING_CXXFLAGS -Wall") + + dnl if asked for, add -Werror if supported + if test "x$1" != "xno" + then + AS_CXX_COMPILER_FLAG(-Werror, ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror") + + if test "x$ERROR_CXXFLAGS" != "x" + then + dnl add exceptions + AS_CXX_COMPILER_FLAG([-Wno-non-virtual-dtor], ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Wno-non-virtual-dtor") + + dnl Add -fno-strict-aliasing for GLib versions before 2.19.8 + dnl as before G_LOCK and friends caused strict aliasing compiler + dnl warnings. + PKG_CHECK_EXISTS([glib-2.0 < 2.19.8], [ + AS_CXX_COMPILER_FLAG([-fno-strict-aliasing], + ERROR_CXXFLAGS="$ERROR_CXXFLAGS -fno-strict-aliasing") + ]) + else + dnl if -Werror isn't suported, try -errwarn=%all + AS_CXX_COMPILER_FLAG([-errwarn=%all], ERROR_CXXFLAGS="$ERROR_CXXFLAGS -errwarn=%all") + if test "x$ERROR_CXXFLAGS" != "x"; then + dnl try -errwarn=%all,no%E_EMPTY_DECLARATION, + dnl no%E_STATEMENT_NOT_REACHED,no%E_ARGUEMENT_MISMATCH, + dnl no%E_MACRO_REDEFINED (Sun Forte case) + dnl For Forte we need disable "empty declaration" warning produced by un-needed semicolon + dnl "statement not reached" disabled because there is g_assert_not_reached () in some places + dnl "macro redefined" because of gst/gettext.h + dnl FIXME: is it really supposed to be 'ARGUEMENT' and not 'ARGUMENT'? + dnl FIXME: do any of these work with the c++ compiler? if not, why + dnl do we check at all? + for f in 'no%E_EMPTY_DECLARATION' \ + 'no%E_STATEMENT_NOT_REACHED' \ + 'no%E_ARGUEMENT_MISMATCH' \ + 'no%E_MACRO_REDEFINED' \ + 'no%E_LOOP_NOT_ENTERED_AT_TOP' + do + AS_CXX_COMPILER_FLAG([-errwarn=%all,$f], [ERROR_CXXFLAGS="$ERROR_CXXFLAGS,$f"]) + done + fi + fi + fi + + if test "x$2" != "x" + then + UNSUPPORTED="" + list="$2" + for each in $list + do + AS_CXX_COMPILER_FLAG($each, + WARNING_CXXFLAGS="$WARNING_CXXFLAGS $each", + UNSUPPORTED="$UNSUPPORTED $each") + done + if test "X$UNSUPPORTED" != X ; then + AC_MSG_NOTICE([unsupported compiler flags: $UNSUPPORTED]) + fi + fi + + AC_SUBST(WARNING_CXXFLAGS) + AC_SUBST(ERROR_CXXFLAGS) + AC_MSG_NOTICE([set WARNING_CXXFLAGS to $WARNING_CXXFLAGS]) + AC_MSG_NOTICE([set ERROR_CXXFLAGS to $ERROR_CXXFLAGS]) +]) + +dnl Sets WARNING_OBJCFLAGS and ERROR_OBJCFLAGS to something the compiler +dnl will accept and AC_SUBST them so they are available in Makefile +dnl +dnl WARNING_OBJCFLAGS will contain flags to make the compiler emit more +dnl warnings. +dnl ERROR_OBJCFLAGS will contain flags to make those warnings fatal, +dnl unless ADD-WERROR is set to "no" +dnl +dnl If MORE_FLAGS is set, tries to add each of the given flags +dnl to WARNING_CFLAGS if the compiler supports them. Each flag is +dnl tested separately. +dnl +dnl These flags can be overridden at make time: +dnl make ERROR_OBJCFLAGS= +AC_DEFUN([AG_GST_SET_ERROR_OBJCFLAGS], +[ + AC_REQUIRE([AC_PROG_OBJC]) + AC_REQUIRE([AS_OBJC_COMPILER_FLAG]) + + ERROR_OBJCFLAGS="" + WARNING_OBJCFLAGS="" + + dnl if we support -Wall, set it unconditionally + AS_OBJC_COMPILER_FLAG(-Wall, WARNING_OBJCFLAGS="$WARNING_OBJCFLAGS -Wall") + + dnl if asked for, add -Werror if supported + if test "x$1" != "xno" + then + AS_OBJC_COMPILER_FLAG(-Werror, ERROR_OBJCFLAGS="$ERROR_OBJCFLAGS -Werror") + + if test "x$ERROR_OBJCFLAGS" != "x" + then + dnl Add -fno-strict-aliasing for GLib versions before 2.19.8 + dnl as before G_LOCK and friends caused strict aliasing compiler + dnl warnings. + PKG_CHECK_EXISTS([glib-2.0 < 2.19.8], [ + AS_OBJC_COMPILER_FLAG([-fno-strict-aliasing], + ERROR_OBJCFLAGS="$ERROR_OBJCFLAGS -fno-strict-aliasing") + ]) + else + dnl if -Werror isn't suported, try -errwarn=%all + AS_OBJC_COMPILER_FLAG([-errwarn=%all], ERROR_OBJCFLAGS="$ERROR_OBJCFLAGS -errwarn=%all") + if test "x$ERROR_OBJCFLAGS" != "x"; then + dnl try -errwarn=%all,no%E_EMPTY_DECLARATION, + dnl no%E_STATEMENT_NOT_REACHED,no%E_ARGUEMENT_MISMATCH, + dnl no%E_MACRO_REDEFINED (Sun Forte case) + dnl For Forte we need disable "empty declaration" warning produced by un-needed semicolon + dnl "statement not reached" disabled because there is g_assert_not_reached () in some places + dnl "macro redefined" because of gst/gettext.h + dnl FIXME: is it really supposed to be 'ARGUEMENT' and not 'ARGUMENT'? + dnl FIXME: do any of these work with the c++ compiler? if not, why + dnl do we check at all? + for f in 'no%E_EMPTY_DECLARATION' \ + 'no%E_STATEMENT_NOT_REACHED' \ + 'no%E_ARGUEMENT_MISMATCH' \ + 'no%E_MACRO_REDEFINED' \ + 'no%E_LOOP_NOT_ENTERED_AT_TOP' + do + AS_OBJC_COMPILER_FLAG([-errwarn=%all,$f], [ERROR_OBJCFLAGS="$ERROR_OBJCFLAGS,$f"]) + done + fi + fi + fi + + if test "x$2" != "x" + then + UNSUPPORTED="" + list="$2" + for each in $list + do + AS_OBJC_COMPILER_FLAG($each, + WARNING_OBJCFLAGS="$WARNING_OBJCFLAGS $each", + UNSUPPORTED="$UNSUPPORTED $each") + done + if test "X$UNSUPPORTED" != X ; then + AC_MSG_NOTICE([unsupported compiler flags: $UNSUPPORTED]) + fi + fi + + AC_SUBST(WARNING_OBJCFLAGS) + AC_SUBST(ERROR_OBJCFLAGS) + AC_MSG_NOTICE([set WARNING_OBJCFLAGS to $WARNING_OBJCFLAGS]) + AC_MSG_NOTICE([set ERROR_OBJCFLAGS to $ERROR_OBJCFLAGS]) +]) + +dnl Sets the default error level for debugging messages +AC_DEFUN([AG_GST_SET_LEVEL_DEFAULT], +[ + dnl define correct errorlevel for debugging messages. We want to have + dnl GST_ERROR messages printed when running cvs builds + if test "x[$1]" = "xyes"; then + GST_LEVEL_DEFAULT=GST_LEVEL_ERROR + else + GST_LEVEL_DEFAULT=GST_LEVEL_NONE + fi + AC_DEFINE_UNQUOTED(GST_LEVEL_DEFAULT, $GST_LEVEL_DEFAULT, + [Default errorlevel to use]) + dnl AC_SUBST so we can use it for win32/common/config.h + AC_SUBST(GST_LEVEL_DEFAULT) +]) diff --git a/common/m4/gst-feature.m4 b/common/m4/gst-feature.m4 new file mode 100644 index 0000000..876215e --- /dev/null +++ b/common/m4/gst-feature.m4 @@ -0,0 +1,297 @@ +dnl Perform a check for a feature for GStreamer +dnl Richard Boulton +dnl Thomas Vander Stichele added useful stuff +dnl Last modification: 25/06/2001 +dnl +dnl AG_GST_CHECK_FEATURE(FEATURE-NAME, FEATURE-DESCRIPTION, +dnl DEPENDENT-PLUGINS, TEST-FOR-FEATURE, +dnl DISABLE-BY-DEFAULT, ACTION-IF-USE, ACTION-IF-NOTUSE) +dnl +dnl This macro adds a command line argument to allow the user to enable +dnl or disable a feature, and if the feature is enabled, performs a supplied +dnl test to check if the feature is available. +dnl +dnl The test should define HAVE_ to "yes" or "no" depending +dnl on whether the feature is available. +dnl +dnl The macro will set USE_ to "yes" or "no" depending on +dnl whether the feature is to be used. +dnl Thomas changed this, so that when USE_ was already set +dnl to no, then it stays that way. +dnl +dnl The macro will call AM_CONDITIONAL(USE_, ...) to allow +dnl the feature to control what is built in Makefile.ams. If you want +dnl additional actions resulting from the test, you can add them with the +dnl ACTION-IF-USE and ACTION-IF-NOTUSE parameters. +dnl +dnl FEATURE-NAME is the name of the feature, and should be in +dnl purely upper case characters. +dnl FEATURE-DESCRIPTION is used to describe the feature in help text for +dnl the command line argument. +dnl DEPENDENT-PLUGINS lists any plug-ins which depend on this feature. +dnl TEST-FOR-FEATURE is a test which sets HAVE_ to "yes" +dnl or "no" depending on whether the feature is +dnl available. +dnl DISABLE-BY-DEFAULT if "disabled", the feature is disabled by default, +dnl if any other value, the feature is enabled by default. +dnl ACTION-IF-USE any extra actions to perform if the feature is to be +dnl used. +dnl ACTION-IF-NOTUSE any extra actions to perform if the feature is not to +dnl be used. +dnl +dnl +dnl thomas : +dnl we also added a history. +dnl GST_PLUGINS_YES will contain all plugins to be built +dnl that were checked through AG_GST_CHECK_FEATURE +dnl GST_PLUGINS_NO will contain those that won't be built + +AC_DEFUN([AG_GST_CHECK_FEATURE], +[echo +AC_MSG_NOTICE(*** checking feature: [$2] ***) +if test "x[$3]" != "x" +then + AC_MSG_NOTICE(*** for plug-ins: [$3] ***) +fi +dnl +builtin(define, [gst_endisable], ifelse($5, [disabled], [enable], [disable]))dnl +dnl if it is set to NO, then don't even consider it for building +NOUSE= +if test "x$USE_[$1]" = "xno"; then + NOUSE="yes" +fi +AC_ARG_ENABLE(translit([$1], A-Z, a-z), + [ ]builtin(format, --%-26s gst_endisable %s, gst_endisable-translit([$1], A-Z, a-z), [$2]ifelse([$3],,,: [$3])), + [ case "${enableval}" in + yes) USE_[$1]=yes;; + no) USE_[$1]=no;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-translit([$1], A-Z, a-z)) ;; + esac], + [ USE_$1=]ifelse($5, [disabled], [no], [yes])) dnl DEFAULT + +dnl *** set it back to no if it was preset to no +if test "x$NOUSE" = "xyes"; then + USE_[$1]="no" + AC_MSG_WARN(*** $3 pre-configured not to be built) +fi +NOUSE= + +dnl *** Check if it is ported or not +if echo " [$GST_PLUGINS_NONPORTED] " | tr , ' ' | grep -i " [$1] " > /dev/null; then + USE_[$1]="no" + AC_MSG_WARN(*** $3 not ported) +fi + +dnl *** If it's enabled + +if test x$USE_[$1] = xyes; then + dnl save compile variables before the test + + gst_check_save_LIBS=$LIBS + gst_check_save_LDFLAGS=$LDFLAGS + gst_check_save_CFLAGS=$CFLAGS + gst_check_save_CPPFLAGS=$CPPFLAGS + gst_check_save_CXXFLAGS=$CXXFLAGS + + HAVE_[$1]=no + dnl TEST_FOR_FEATURE + $4 + + LIBS=$gst_check_save_LIBS + LDFLAGS=$gst_check_save_LDFLAGS + CFLAGS=$gst_check_save_CFLAGS + CPPFLAGS=$gst_check_save_CPPFLAGS + CXXFLAGS=$gst_check_save_CXXFLAGS + + dnl If it isn't found, unset USE_[$1] + if test x$HAVE_[$1] = xno; then + USE_[$1]=no + else + ifelse([$3], , :, [AC_MSG_NOTICE(*** These plugins will be built: [$3])]) + fi +fi +dnl *** Warn if it's disabled or not found +if test x$USE_[$1] = xyes; then + ifelse([$6], , :, [$6]) + if test "x$3" != "x"; then + GST_PLUGINS_YES="\t[$3]\n$GST_PLUGINS_YES" + fi + AC_DEFINE(HAVE_[$1], , [Define to enable $2]ifelse($3,,, [ (used by $3)]).) +else + ifelse([$3], , :, [AC_MSG_NOTICE(*** These plugins will not be built: [$3])]) + if test "x$3" != "x"; then + GST_PLUGINS_NO="\t[$3]\n$GST_PLUGINS_NO" + fi + ifelse([$7], , :, [$7]) +fi +dnl *** Define the conditional as appropriate +AM_CONDITIONAL(USE_[$1], test x$USE_[$1] = xyes) +]) + +dnl Use AC_CHECK_LIB and AC_CHECK_HEADER to do both tests at once +dnl sets HAVE_module if we have it +dnl Richard Boulton +dnl Last modification: 26/06/2001 +dnl AG_GST_CHECK_LIBHEADER(FEATURE-NAME, LIB NAME, LIB FUNCTION, EXTRA LD FLAGS, +dnl HEADER NAME, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) +dnl +dnl This check was written for GStreamer: it should be renamed and checked +dnl for portability if you decide to use it elsewhere. +dnl +AC_DEFUN([AG_GST_CHECK_LIBHEADER], +[ + AC_CHECK_LIB([$2], [$3], HAVE_[$1]=yes, HAVE_[$1]=no,[$4]) + if test "x$HAVE_[$1]" = "xyes"; then + AC_CHECK_HEADER([$5], :, HAVE_[$1]=no) + if test "x$HAVE_[$1]" = "xyes"; then + dnl execute what needs to be + ifelse([$6], , :, [$6]) + else + ifelse([$7], , :, [$7]) + fi + else + ifelse([$7], , :, [$7]) + fi + AC_SUBST(HAVE_[$1]) +] +) + +dnl 2004-02-14 Thomas - changed to get set properly and use proper output +dnl 2003-06-27 Benjamin Otte - changed to make this work with gstconfig.h +dnl +dnl Add a subsystem --disable flag and all the necessary symbols and substitions +dnl +dnl AG_GST_CHECK_SUBSYSTEM_DISABLE(SYSNAME, [subsystem name]) +dnl +AC_DEFUN([AG_GST_CHECK_SUBSYSTEM_DISABLE], +[ + dnl this define will replace each literal subsys_def occurrence with + dnl the lowercase hyphen-separated subsystem + dnl e.g. if $1 is GST_DEBUG then subsys_def will be a macro with gst-debug + define([subsys_def],translit([$1], _A-Z, -a-z)) + + AC_ARG_ENABLE(subsys_def, + AC_HELP_STRING(--disable-subsys_def, [disable $2]), + [ + case "${enableval}" in + yes) GST_DISABLE_[$1]=no ;; + no) GST_DISABLE_[$1]=yes ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-subsys_def]) ;; + esac + ], + [GST_DISABLE_[$1]=no]) dnl Default value + + if test x$GST_DISABLE_[$1] = xyes; then + AC_MSG_NOTICE([disabled subsystem [$2]]) + GST_DISABLE_[$1]_DEFINE="#define GST_DISABLE_$1 1" + else + GST_DISABLE_[$1]_DEFINE="/* #undef GST_DISABLE_$1 */" + fi + AC_SUBST(GST_DISABLE_[$1]_DEFINE) + undefine([subsys_def]) +]) + + +dnl Parse gstconfig.h for feature and defines add the symbols and substitions +dnl +dnl AG_GST_PARSE_SUBSYSTEM_DISABLE(GST_CONFIGPATH, FEATURE) +dnl +AC_DEFUN([AG_GST_PARSE_SUBSYSTEM_DISABLE], +[ + grep >/dev/null "#undef GST_DISABLE_$2" $1 + if test $? = 0; then + GST_DISABLE_[$2]=0 + else + GST_DISABLE_[$2]=1 + fi + AC_SUBST(GST_DISABLE_[$2]) +]) + +dnl Parse gstconfig.h and defines add the symbols and substitions +dnl +dnl GST_CONFIGPATH=`$PKG_CONFIG --variable=includedir gstreamer-1.0`"/gst/gstconfig.h" +dnl AG_GST_PARSE_SUBSYSTEM_DISABLES(GST_CONFIGPATH) +dnl +AC_DEFUN([AG_GST_PARSE_SUBSYSTEM_DISABLES], +[ + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,GST_DEBUG) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,LOADSAVE) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,PARSE) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,TRACE) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,ALLOC_TRACE) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,REGISTRY) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,PLUGIN) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,XML) +]) + +dnl AG_GST_CHECK_GST_DEBUG_DISABLED(ACTION-IF-DISABLED, ACTION-IF-NOT-DISABLED) +dnl +dnl Checks if the GStreamer debugging system is disabled in the core version +dnl we are compiling against (by checking gstconfig.h) +dnl +AC_DEFUN([AG_GST_CHECK_GST_DEBUG_DISABLED], +[ + AC_REQUIRE([AG_GST_CHECK_GST]) + + AC_MSG_CHECKING([whether the GStreamer debugging system is enabled]) + AC_LANG_PUSH([C]) + save_CFLAGS="$CFLAGS" + CFLAGS="$GST_CFLAGS $CFLAGS" + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([[ + #include + #ifdef GST_DISABLE_GST_DEBUG + #error "debugging disabled, make compiler fail" + #endif]])], [ debug_system_enabled=yes], [debug_system_enabled=no]) + CFLAGS="$save_CFLAGS" + AC_LANG_POP([C]) + + AC_MSG_RESULT([$debug_system_enabled]) + + if test "x$debug_system_enabled" = "xyes" ; then + $2 + true + else + $1 + true + fi +]) + +dnl relies on GST_PLUGINS_ALL, GST_PLUGINS_SELECTED, GST_PLUGINS_YES, +dnl GST_PLUGINS_NO, and BUILD_EXTERNAL +AC_DEFUN([AG_GST_OUTPUT_PLUGINS], [ + +printf "configure: *** Plug-ins without external dependencies that will be built:\n" +( for i in $GST_PLUGINS_SELECTED; do printf '\t'$i'\n'; done ) | sort +printf "\n" + +printf "configure: *** Plug-ins without external dependencies that will NOT be built:\n" +( for i in $GST_PLUGINS_ALL; do + case " $GST_PLUGINS_SELECTED " in + *\ $i\ *) + ;; + *) + printf '\t'$i'\n' + ;; + esac + done ) | sort +printf "\n" + +printf "configure: *** Plug-ins that have NOT been ported:\n" +( for i in $GST_PLUGINS_NONPORTED; do + printf '\t'$i'\n' + done ) | sort +printf "\n" + +if test "x$BUILD_EXTERNAL" = "xno"; then + printf "configure: *** No plug-ins with external dependencies will be built\n" +else + printf "configure: *** Plug-ins with dependencies that will be built:" + printf "$GST_PLUGINS_YES\n" | sort + printf "\n" + printf "configure: *** Plug-ins with dependencies that will NOT be built:" + printf "$GST_PLUGINS_NO\n" | sort + printf "\n" +fi +]) + diff --git a/common/m4/gst-function.m4 b/common/m4/gst-function.m4 new file mode 100644 index 0000000..61adfd3 --- /dev/null +++ b/common/m4/gst-function.m4 @@ -0,0 +1,63 @@ +dnl +dnl Check for compiler mechanism to show functions in debugging +dnl copied from an Ali patch floating on the internet +dnl +AC_DEFUN([AG_GST_CHECK_FUNCTION],[ + dnl #1: __PRETTY_FUNCTION__ + AC_MSG_CHECKING(whether $CC implements __PRETTY_FUNCTION__) + AC_CACHE_VAL(gst_cv_have_pretty_function,[ + AC_TRY_LINK([#include ], + [printf("%s", __PRETTY_FUNCTION__);], + gst_cv_have_pretty_function=yes, + gst_cv_have_pretty_function=no) + ]) + AC_MSG_RESULT($gst_cv_have_pretty_function) + if test "$gst_cv_have_pretty_function" = yes; then + AC_DEFINE(HAVE_PRETTY_FUNCTION, 1, + [defined if the compiler implements __PRETTY_FUNCTION__]) + fi + +dnl #2: __FUNCTION__ + AC_MSG_CHECKING(whether $CC implements __FUNCTION__) + AC_CACHE_VAL(gst_cv_have_function,[ + AC_TRY_LINK([#include ], + [printf("%s", __FUNCTION__);], + gst_cv_have_function=yes, + gst_cv_have_function=no) + ]) + AC_MSG_RESULT($gst_cv_have_function) + if test "$gst_cv_have_function" = yes; then + AC_DEFINE(HAVE_FUNCTION, 1, + [defined if the compiler implements __FUNCTION__]) + fi + +dnl #3: __func__ + AC_MSG_CHECKING(whether $CC implements __func__) + AC_CACHE_VAL(gst_cv_have_func,[ + AC_TRY_LINK([#include ], + [printf("%s", __func__);], + gst_cv_have_func=yes, + gst_cv_have_func=no) + ]) + AC_MSG_RESULT($gst_cv_have_func) + if test "$gst_cv_have_func" = yes; then + AC_DEFINE(HAVE_FUNC, 1, + [defined if the compiler implements __func__]) + fi + +dnl now define FUNCTION to whatever works, and fallback to "" + if test "$gst_cv_have_pretty_function" = yes; then + function=__PRETTY_FUNCTION__ + else + if test "$gst_cv_have_function" = yes; then + function=__FUNCTION__ + else + if test "$gst_cv_have_func" = yes; then + function=__func__ + else + function=\"\" + fi + fi + fi + AC_DEFINE_UNQUOTED(GST_FUNCTION, $function, [macro to use to show function name]) +]) diff --git a/common/m4/gst-gettext.m4 b/common/m4/gst-gettext.m4 new file mode 100644 index 0000000..df817eb --- /dev/null +++ b/common/m4/gst-gettext.m4 @@ -0,0 +1,28 @@ +dnl gettext setup + +dnl AG_GST_GETTEXT([gettext-package]) +dnl defines GETTEXT_PACKAGE and LOCALEDIR + +AC_DEFUN([AG_GST_GETTEXT], +[ + if test "$USE_NLS" = "yes"; then + GETTEXT_PACKAGE=[$1] + else + GETTEXT_PACKAGE=[NULL] + fi + AC_SUBST(GETTEXT_PACKAGE) + AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], "$GETTEXT_PACKAGE", + [gettext package name]) + + dnl make sure po/Makevars is kept in sync with GETTEXT_PACKAGE + if test -e "${srcdir}/po/Makevars"; then + if ! grep -e "$1" "${srcdir}/po/Makevars"; then + AC_MSG_ERROR([DOMAIN in po/Makevars does not match GETTEXT_PACKAGE $1]) + fi + fi + + dnl define LOCALEDIR in config.h + AS_AC_EXPAND(LOCALEDIR, $datadir/locale) + AC_DEFINE_UNQUOTED([LOCALEDIR], "$LOCALEDIR", + [gettext locale dir]) +]) diff --git a/common/m4/gst-glib2.m4 b/common/m4/gst-glib2.m4 new file mode 100644 index 0000000..63f0f46 --- /dev/null +++ b/common/m4/gst-glib2.m4 @@ -0,0 +1,126 @@ +dnl check for a minimum version of GLib + +dnl AG_GST_GLIB_CHECK([minimum-version-required]) + +AC_DEFUN([AG_GST_GLIB_CHECK], +[ + AC_REQUIRE([AS_NANO]) + + dnl Minimum required version of GLib + GLIB_REQ=[$1] + if test "x$GLIB_REQ" = "x" + then + AC_MSG_ERROR([Please specify a required version for GLib 2.0]) + fi + AC_SUBST(GLIB_REQ) + + dnl Check for glib with everything + AG_GST_PKG_CHECK_MODULES(GLIB, + glib-2.0 >= $GLIB_REQ gobject-2.0 gmodule-no-export-2.0) + + if test "x$HAVE_GLIB" = "xno"; then + AC_MSG_ERROR([This package requires GLib >= $GLIB_REQ to compile.]) + fi + + dnl Add define to tell GLib that threading is always enabled within GStreamer + dnl code (optimisation, bypasses checks if the threading system is enabled + dnl when using threading primitives) + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_THREADS_MANDATORY" + + dnl Define G_DISABLE_DEPRECATED for development versions + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_DEPRECATED" + fi + + AC_ARG_ENABLE(gobject-cast-checks, + AS_HELP_STRING([--enable-gobject-cast-checks[=@<:@no/auto/yes@:>@]], + [Enable GObject cast checks]),[enable_gobject_cast_checks=$enableval], + [enable_gobject_cast_checks=auto]) + + if test "x$enable_gobject_cast_checks" = "xauto"; then + dnl Turn on cast checks only for development versions + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then + enable_gobject_cast_checks=yes + else + enable_gobject_cast_checks=no + fi + fi + + if test "x$enable_gobject_cast_checks" = "xno"; then + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_CAST_CHECKS" + fi + + AC_ARG_ENABLE(glib-asserts, + AS_HELP_STRING([--enable-glib-asserts[=@<:@no/auto/yes@:>@]], + [Enable GLib assertion]),[enable_glib_assertions=$enableval], + [enable_glib_assertions=auto]) + + if test "x$enable_glib_assertions" = "xauto"; then + dnl Enable assertions only for development versions + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then + enable_glib_assertions=yes + else + enable_glib_assertions=no + fi + fi + + if test "x$enable_glib_assertions" = "xno"; then + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_ASSERT" + fi + + dnl Find location of glib utils. People may want to or have to override these, + dnl e.g. in a cross-compile situation where PATH is a bit messed up. We need + dnl for these tools to work on the host, so can't just use the one from the + dnl GLib installation that pkg-config picks up, as that might be for a + dnl different target architecture. + dnl + dnl glib-genmarshal: + AC_MSG_CHECKING(for glib-genmarshal) + if test "x$GLIB_GENMARSHAL" != "x"; then + AC_MSG_RESULT([$GLIB_GENMARSHAL (from environment)]) + else + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + if $GLIB_GENMARSHAL --version 2>/dev/null >/dev/null; then + AC_MSG_RESULT([$GLIB_GENMARSHAL (from pkg-config path)]) + else + AC_PATH_PROG(GLIB_GENMARSHAL, [glib-genmarshal], [glib-genmarshal]) + AC_MSG_RESULT([$GLIB_GENMARSHAL]) + fi + fi + if ! $GLIB_GENMARSHAL --version 2>/dev/null >/dev/null; then + AC_MSG_WARN([$GLIB_GENMARSHAL does not seem to work!]) + fi + AC_SUBST(GLIB_GENMARSHAL) + + dnl glib-mkenums: + AC_MSG_CHECKING(for glib-mkenums) + if test "x$GLIB_MKENUMS" != "x"; then + AC_MSG_RESULT([$GLIB_MKENUMS (from environment)]) + else + dnl glib-mkenums is written in perl so should always work really + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + AC_MSG_RESULT([$GLIB_MKENUMS]) + fi + if ! $GLIB_MKENUMS --version 2>/dev/null >/dev/null; then + AC_MSG_WARN([$GLIB_MKENUMS does not seem to work!]) + fi + AC_SUBST(GLIB_MKENUMS) + + AC_SUBST(GLIB_EXTRA_CFLAGS) + + dnl Now check for GIO + PKG_CHECK_MODULES(GIO, gio-2.0 >= $GLIB_REQ) + if test "x$HAVE_GIO" = "xno"; then + AC_MSG_ERROR([This package requires GIO >= $GLIB_REQ to compile.]) + fi + + GIO_MODULE_DIR="`$PKG_CONFIG --variable=giomoduledir gio-2.0`" + AC_DEFINE_UNQUOTED(GIO_MODULE_DIR, "$GIO_MODULE_DIR", + [The GIO modules directory.]) + GIO_LIBDIR="`$PKG_CONFIG --variable=libdir gio-2.0`" + AC_DEFINE_UNQUOTED(GIO_LIBDIR, "$GIO_LIBDIR", + [The GIO library directory.]) + AC_SUBST(GIO_CFLAGS) + AC_SUBST(GIO_LIBS) + AC_SUBST(GIO_LDFLAGS) +]) diff --git a/common/m4/gst-libxml2.m4 b/common/m4/gst-libxml2.m4 new file mode 100644 index 0000000..4a843f0 --- /dev/null +++ b/common/m4/gst-libxml2.m4 @@ -0,0 +1,52 @@ +dnl call this macro with the minimum required version as an argument +dnl this macro sets and AC_SUBSTs XML_CFLAGS and XML_LIBS +dnl it also sets LIBXML_PKG, used for the pkg-config file + +AC_DEFUN([AG_GST_LIBXML2_CHECK], +[ + dnl Minimum required version of libxml2 + dnl default to 2.4.9 if not specified + LIBXML2_REQ=ifelse([$1],,2.4.9,[$1]) + AC_SUBST(LIBXML2_REQ) + + dnl check for libxml2 + PKG_CHECK_MODULES(XML, libxml-2.0 >= $LIBXML2_REQ, + HAVE_LIBXML2=yes, [ + AC_MSG_RESULT(no) + HAVE_LIBXML2=no + ]) + if test "x$HAVE_LIBXML2" = "xyes"; then + AC_DEFINE(HAVE_LIBXML2, 1, [Define if libxml2 is available]) + else + AC_MSG_ERROR([ + Need libxml2 and development headers/files to build GStreamer. + + You can do without libxml2 if you pass --disable-loadsave to + configure, but that breaks ABI, so don't do that unless you + are building for an embedded setup and know what you are doing. + ]) + fi + dnl this is for the .pc file + LIBXML_PKG=', libxml-2.0' + AC_SUBST(LIBXML_PKG) + AC_SUBST(XML_LIBS) + AC_SUBST(XML_CFLAGS) + + dnl XML_LIBS might pull in -lz without zlib actually being on the system, so + dnl try linking with these LIBS and CFLAGS + ac_save_CFLAGS=$CFLAGS + ac_save_LIBS=$LIBS + CFLAGS="$CFLAGS $XML_CFLAGS" + LIBS="$LIBS $XML_LIBS" + AC_TRY_LINK([ +#include +#include +],[ +/* function body */ +], + AC_MSG_NOTICE([Test xml2 program linked]), + AC_MSG_ERROR([Could not link libxml2 test program. Check if you have the necessary dependencies.]) + ) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" +]) diff --git a/common/m4/gst-package-release-datetime.m4 b/common/m4/gst-package-release-datetime.m4 new file mode 100644 index 0000000..bc885e3 --- /dev/null +++ b/common/m4/gst-package-release-datetime.m4 @@ -0,0 +1,89 @@ +dnl macros to set GST_PACKAGE_RELEASE_DATETIME + +dnl =========================================================================== +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME +dnl +dnl Usage: +dnl +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME() +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([no]...) +dnl sets the release datetime to the current date +dnl (no = this is not a release, but git or prerelease) +dnl +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([YYYY-MM-DD]) +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes], [YYYY-MM-DD]) +dnl sets the release datetime to the specified date (and time, if given) +dnl (yes = this is a release, not git or prerelease) +dnl +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes], [DOAP-FILE], [RELEASE-VERSION]) +dnl sets the release date to the release date associated with version +dnl RELEASE-VERSION in the .doap file DOAP-FILE +dnl (yes = this is a release, not git or prerelease) +dnl +dnl We need to treat pre-releases like git because there won't be an entry +dnl in the .doap file for pre-releases yet, and we don't want to use the +dnl date of the last release either. +dnl =========================================================================== +AC_DEFUN([AG_GST_SET_PACKAGE_RELEASE_DATETIME], +[ + dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME() + dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes]...) + if test "x$1" = "xno" -o "x$1" = "x"; then + GST_PACKAGE_RELEASE_DATETIME=`date -u "+%Y-%m-%dT%H:%MZ"` + elif test "x$1" = "xyes"; then + dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([no], ["YYYY-MM-DD"]) + dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([no], [DOAP-FILE], [RELEASE-VERSION]) + if ( echo $1 | grep '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then + GST_PACKAGE_RELEASE_DATETIME=$1 + else + dnl we assume the .doap file contains the date as YYYY-MM-DD + YYYY_MM_DD=`sh "${srcdir}/common/extract-release-date-from-doap-file" $3 $2`; + if test "x$YYYY_MM_DD" != "x"; then + GST_PACKAGE_RELEASE_DATETIME=$YYYY_MM_DD + else + AC_MSG_ERROR([SET_PACKAGE_RELEASE_DATETIME: could not extract + release date for release version $3 from $2]) + GST_PACKAGE_RELEASE_DATETIME="" + fi + fi + dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([YYYY-MM-DD]) + elif ( echo $1 | grep '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then + GST_PACKAGE_RELEASE_DATETIME=$1 + else + AC_MSG_WARN([SET_PACKAGE_RELEASE_DATETIME: invalid first argument]) + GST_PACKAGE_RELEASE_DATETIME="" + fi + + if test "x$GST_PACKAGE_RELEASE_DATETIME" = "x"; then + AC_MSG_WARN([Invalid package release date time: $GST_PACKAGE_RELEASE_DATETIME]) + else + AC_MSG_NOTICE([Setting GST_PACKAGE_RELEASE_DATETIME to $GST_PACKAGE_RELEASE_DATETIME]) + + AC_DEFINE_UNQUOTED([GST_PACKAGE_RELEASE_DATETIME], + ["$GST_PACKAGE_RELEASE_DATETIME"], + [GStreamer package release date/time for plugins as YYYY-MM-DD]) + fi +]) + +dnl =========================================================================== +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO +dnl +dnl Usage: +dnl +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([NANO-VERSION], [DOAP-FILE], [RELEASE-VERSION]) +dnl if NANO-VERSION is 0, sets the release date to the release date associated +dnl with version RELEASE-VERSION in the .doap file DOAP-FILE, otherwise sets +dnl the release date and time to the current date/time. +dnl +dnl We need to treat pre-releases like git because there won't be an entry +dnl in the .doap file for pre-releases yet, and we don't want to use the +dnl date of the last release either. +dnl =========================================================================== +AC_DEFUN([AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO], +[ + if test "x$1" = "x0"; then + AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes], [ $2 ], [ $3 ]) + else + AG_GST_SET_PACKAGE_RELEASE_DATETIME([no]) + fi +]) diff --git a/common/m4/gst-parser.m4 b/common/m4/gst-parser.m4 new file mode 100644 index 0000000..b002047 --- /dev/null +++ b/common/m4/gst-parser.m4 @@ -0,0 +1,55 @@ +AC_DEFUN([AG_GST_BISON_CHECK], +[ + dnl FIXME: check if AC_PROG_YACC is suitable here + dnl FIXME: make precious + AC_PATH_PROG(BISON_PATH, bison, no) + if test x$BISON_PATH = xno; then + AC_MSG_ERROR(Could not find bison) + fi + + dnl check bison version + dnl we need version >= 2.4 for the '<>' support + dnl in the parser. + dnl First lines observed: 'bison (GNU Bison) 2.3' or 'GNU Bison version 1.28' + bison_min_version=2.4 + bison_version=`$BISON_PATH --version | head -n 1 | sed 's/^[[^0-9]]*//' | sed 's/[[^0-9]]*$//' | cut -d' ' -f1` + AC_MSG_CHECKING([bison version $bison_version >= $bison_min_version]) + + if perl -we "exit ((v$bison_version ge v$bison_min_version) ? 0 : 1)"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_ERROR([no]) + fi +]) + +AC_DEFUN([AG_GST_FLEX_CHECK], +[ + dnl we require flex for building the parser + AC_PATH_PROG(FLEX_PATH, flex, no) + if test x$FLEX_PATH = xno; then + AC_MSG_ERROR(Could not find flex) + fi + + dnl check flex version + dnl we need version >= 2.5.31 for the reentrancy support + dnl in the parser. + flex_min_version=2.5.31 + flex_version=`$FLEX_PATH --version | head -n 1 | awk '{print $2}'` + AC_MSG_CHECKING([flex version $flex_version >= $flex_min_version]) + if perl -w < \$min_version_major) || + ((\$flex_version_major == \$min_version_major) && + (\$flex_version_minor > \$min_version_minor)) || + ((\$flex_version_major == \$min_version_major) && + (\$flex_version_minor == \$min_version_minor) && + (\$flex_version_micro >= \$min_version_micro))) + ? 0 : 1); +EOF + then + AC_MSG_RESULT(yes) + else + AC_MSG_ERROR([no]) + fi +]) diff --git a/common/m4/gst-platform.m4 b/common/m4/gst-platform.m4 new file mode 100644 index 0000000..40d6faf --- /dev/null +++ b/common/m4/gst-platform.m4 @@ -0,0 +1,67 @@ +dnl AG_GST_PLATFORM +dnl Check for platform specific features and define some variables +dnl +dnl GST_EXTRA_MODULE_SUFFIX: contains a platform specific +dnl extra module suffix additional to G_MODULE_SUFFIX +dnl +dnl HAVE_OSX: Defined if compiling for OS X +dnl +dnl GST_HAVE_UNSAFE_FORK: Defined if fork is unsafe (Windows) +dnl +dnl HAVE_WIN32: Defined if compiling on Win32 +dnl + +AC_DEFUN([AG_GST_PLATFORM], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + + case $host_os in + rhapsody*) + AC_DEFINE_UNQUOTED(GST_EXTRA_MODULE_SUFFIX, [".dylib"], [Extra platform specific plugin suffix]) + ;; + darwin*) + AC_DEFINE_UNQUOTED(GST_EXTRA_MODULE_SUFFIX, [".dylib"], [Extra platform specific plugin suffix]) + AC_DEFINE_UNQUOTED(HAVE_OSX, 1, [Defined if compiling for OSX]) + ;; + cygwin*) + AC_DEFINE_UNQUOTED(GST_HAVE_UNSAFE_FORK, 1, [Defined when registry scanning through fork is unsafe]) + ;; + mingw* | msvc* | mks*) + dnl HAVE_WIN32 currently means "disable POSIXisms". + AC_DEFINE_UNQUOTED(HAVE_WIN32, 1, [Defined if compiling for Windows]) + + dnl define __MSVCRT_VERSION__ version if not set already by the + dnl compiler (ie. mostly for mingw). This is needed for things like + dnl __stat64 to be available. If set by the compiler, ensure it's + dnl new enough - we need at least WinXP SP2. + AC_TRY_COMPILE([ ], [ return __MSVCRT_VERSION__; ], [ + AC_TRY_COMPILE([ ], [ + #if __MSVCRT_VERSION__ < 0x0601 + #error "MSVCRT too old" + #endif + ], [ + AC_MSG_NOTICE([MSVCRT version looks ok]) + ], [ + AC_MSG_ERROR([MSVCRT version too old, need at least WinXP SP2]) + ]) + ], [ + AC_MSG_NOTICE([Setting MSVCRT version to 0x0601]) + AC_DEFINE_UNQUOTED(__MSVCRT_VERSION__, 0x0601, [We need at least WinXP SP2 for __stat64]) + ]) + ;; + *) + ;; + esac +]) + +AC_DEFUN([AG_GST_LIBTOOL_PREPARE], +[ + dnl Persuade libtool to also link (-l) a 'pure' (DirectX) static lib, + dnl i.e. as opposed to only import lib with dll counterpart. + dnl Needs to be tweaked before libtool's checks. + case $host_os in + cygwin* | mingw*) + lt_cv_deplibs_check_method=pass_all + ;; + esac +]) \ No newline at end of file diff --git a/common/m4/gst-plugin-docs.m4 b/common/m4/gst-plugin-docs.m4 new file mode 100644 index 0000000..0e2ab6e --- /dev/null +++ b/common/m4/gst-plugin-docs.m4 @@ -0,0 +1,25 @@ +dnl AG_GST_PLUGIN_DOCS([MINIMUM-GTK-DOC-VERSION]) +dnl +dnl checks for prerequisites for the common/mangle-tmpl.py script +dnl used when building the plugin documentation + +AC_DEFUN([AG_GST_PLUGIN_DOCS], +[ + AC_BEFORE([GTK_DOC_CHECK],[$0])dnl check for gtk-doc first + AC_REQUIRE([AM_PATH_PYTHON])dnl find python first + + build_plugin_docs=no + AC_MSG_CHECKING([whether to build plugin documentation]) + if test x$enable_gtk_doc = xyes; then + if test x$PYTHON != x; then + build_plugin_docs=yes + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no (python not found)]) + fi + else + AC_MSG_RESULT([no (gtk-doc disabled or not available)]) + fi + + AM_CONDITIONAL(ENABLE_PLUGIN_DOCS, test x$build_plugin_docs = xyes) +]) diff --git a/common/m4/gst-plugindir.m4 b/common/m4/gst-plugindir.m4 new file mode 100644 index 0000000..c9e1301 --- /dev/null +++ b/common/m4/gst-plugindir.m4 @@ -0,0 +1,17 @@ +dnl AG_GST_SET_PLUGINDIR + +dnl AC_DEFINE PLUGINDIR to the full location where plug-ins will be installed +dnl AC_SUBST plugindir, to be used in Makefile.am's + +AC_DEFUN([AG_GST_SET_PLUGINDIR], +[ + dnl define location of plugin directory + AS_AC_EXPAND(PLUGINDIR, ${libdir}/gstreamer-$GST_API_VERSION) + AC_DEFINE_UNQUOTED(PLUGINDIR, "$PLUGINDIR", + [directory where plugins are located]) + AC_MSG_NOTICE([Using $PLUGINDIR as the plugin install location]) + + dnl plugin directory configure-time variable for use in Makefile.am + plugindir="\$(libdir)/gstreamer-$GST_API_VERSION" + AC_SUBST(plugindir) +]) diff --git a/common/m4/gst-valgrind.m4 b/common/m4/gst-valgrind.m4 new file mode 100644 index 0000000..5c0d608 --- /dev/null +++ b/common/m4/gst-valgrind.m4 @@ -0,0 +1,35 @@ +AC_DEFUN([AG_GST_VALGRIND_CHECK], +[ + dnl valgrind inclusion + AC_ARG_ENABLE(valgrind, + AC_HELP_STRING([--disable-valgrind], [disable run-time valgrind detection]), + [ + case "${enableval}" in + yes) USE_VALGRIND="$USE_DEBUG" ;; + no) USE_VALGRIND=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-valgrind) ;; + esac], + [ + USE_VALGRIND="$USE_DEBUG" + ]) dnl Default value + + VALGRIND_REQ="3.0" + if test "x$USE_VALGRIND" = xyes; then + PKG_CHECK_MODULES(VALGRIND, valgrind >= $VALGRIND_REQ, + USE_VALGRIND="yes", + [ + USE_VALGRIND="no" + AC_MSG_RESULT([no]) + ]) + fi + + if test "x$USE_VALGRIND" = xyes; then + AC_DEFINE(HAVE_VALGRIND, 1, [Define if valgrind should be used]) + AC_MSG_NOTICE(Using extra code paths for valgrind) + fi + AC_SUBST(VALGRIND_CFLAGS) + AC_SUBST(VALGRIND_LIBS) + + AC_PATH_PROG(VALGRIND_PATH, valgrind, no) + AM_CONDITIONAL(HAVE_VALGRIND, test ! "x$VALGRIND_PATH" = "xno") +]) diff --git a/common/m4/gst-x11.m4 b/common/m4/gst-x11.m4 new file mode 100644 index 0000000..d3baf2d --- /dev/null +++ b/common/m4/gst-x11.m4 @@ -0,0 +1,70 @@ +dnl macros for X-related detections +dnl AC_SUBST's HAVE_X, X_CFLAGS, X_LIBS +AC_DEFUN([AG_GST_CHECK_X], +[ + AC_PATH_XTRA + ac_cflags_save="$CFLAGS" + ac_cppflags_save="$CPPFLAGS" + CFLAGS="$CFLAGS $X_CFLAGS" + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + dnl now try to find the HEADER + AC_CHECK_HEADER(X11/Xlib.h, HAVE_X="yes", HAVE_X="no") + + if test "x$HAVE_X" = "xno" + then + AC_MSG_NOTICE([cannot find X11 development files]) + else + dnl this is much more than we want + X_LIBS="$X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS" + dnl AC_PATH_XTRA only defines the path needed to find the X libs, + dnl it does not add the libs; therefore we add them here + X_LIBS="$X_LIBS -lX11" + AC_SUBST(X_CFLAGS) + AC_SUBST(X_LIBS) + fi + AC_SUBST(HAVE_X) + + CFLAGS="$ac_cflags_save" + CPPFLAGS="$ac_cppflags_save" +]) + +dnl *** XVideo *** +dnl Look for the PIC library first, Debian requires it. +dnl Check debian-devel archives for gory details. +dnl 20020110: +dnl At the moment XFree86 doesn't distribute shared libXv due +dnl to unstable API. On many platforms you CAN NOT link a shared +dnl lib to a static non-PIC lib. This is what the xvideo GStreamer +dnl plug-in wants to do. So Debian distributes a PIC compiled +dnl version of the static lib for plug-ins to link to when it is +dnl inappropriate to link the main application to libXv directly. +dnl FIXME: add check if this platform can support linking to a +dnl non-PIC libXv, if not then don not use Xv. +dnl FIXME: perhaps warn user if they have a shared libXv since +dnl this is an error until XFree86 starts shipping one +AC_DEFUN([AG_GST_CHECK_XV], +[ + if test x$HAVE_X = xyes; then + AC_CHECK_LIB(Xv_pic, XvQueryExtension, + HAVE_XVIDEO="yes", HAVE_XVIDEO="no", + $X_LIBS -lXext) + + if test x$HAVE_XVIDEO = xyes; then + XVIDEO_LIBS="-lXv_pic -lXext" + AC_SUBST(XVIDEO_LIBS) + else + dnl try again using something else if we didn't find it first + if test x$HAVE_XVIDEO = xno; then + AC_CHECK_LIB(Xv, XvQueryExtension, + HAVE_XVIDEO="yes", HAVE_XVIDEO="no", + $X_LIBS -lXext) + + if test x$HAVE_XVIDEO = xyes; then + XVIDEO_LIBS="-lXv -lXext" + AC_SUBST(XVIDEO_LIBS) + fi + fi + fi + fi +]) diff --git a/common/m4/gst.m4 b/common/m4/gst.m4 new file mode 100644 index 0000000..d4c53cb --- /dev/null +++ b/common/m4/gst.m4 @@ -0,0 +1,36 @@ +dnl AG_GST_INIT +dnl sets up use of GStreamer configure.ac macros +dnl all GStreamer autoconf macros are prefixed +dnl with AG_GST_ for public macros +dnl with _AG_GST_ for private macros +dnl +dnl We call AC_CANONICAL_TARGET and AC_CANONICAL_HOST so that +dnl it is valid before AC_ARG_PROGRAM is called + +AC_DEFUN([AG_GST_INIT], +[ + m4_pattern_forbid(^_?AG_GST_) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use host_ variables + AC_REQUIRE([AC_CANONICAL_TARGET]) dnl we use target_ variables +]) + +dnl AG_GST_PKG_CONFIG_PATH +dnl +dnl sets up a GST_PKG_CONFIG_PATH variable for use in Makefile.am +dnl which contains the path of the in-tree pkgconfig directory first +dnl and then any paths specified in PKG_CONFIG_PATH. +dnl +dnl We do this mostly so we don't have to use unportable shell constructs +dnl such as ${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH} in Makefile.am to handle +dnl the case where the environment variable is not set, but also in order +dnl to avoid a trailing ':' in the PKG_CONFIG_PATH which apparently causes +dnl problems with pkg-config on windows with msys/mingw. +AC_DEFUN([AG_GST_PKG_CONFIG_PATH], +[ + GST_PKG_CONFIG_PATH="\$(top_builddir)/pkgconfig" + if test "x$PKG_CONFIG_PATH" != "x"; then + GST_PKG_CONFIG_PATH="$GST_PKG_CONFIG_PATH:$PKG_CONFIG_PATH" + fi + AC_SUBST([GST_PKG_CONFIG_PATH]) + AC_MSG_NOTICE([Using GST_PKG_CONFIG_PATH = $GST_PKG_CONFIG_PATH]) +]) diff --git a/common/m4/gtk-doc.m4 b/common/m4/gtk-doc.m4 new file mode 100644 index 0000000..b243f1c --- /dev/null +++ b/common/m4/gtk-doc.m4 @@ -0,0 +1,70 @@ +dnl -*- mode: autoconf -*- + +# serial 1 + +dnl Usage: +dnl GTK_DOC_CHECK([minimum-gtk-doc-version]) +AC_DEFUN([GTK_DOC_CHECK], +[ + AC_REQUIRE([PKG_PROG_PKG_CONFIG]) + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + + dnl check for tools we added during development + AC_PATH_PROG([GTKDOC_CHECK],[gtkdoc-check]) + AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true]) + AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf]) + + dnl for overriding the documentation installation directory + AC_ARG_WITH([html-dir], + AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),, + [with_html_dir='${datadir}/gtk-doc/html']) + HTML_DIR="$with_html_dir" + AC_SUBST([HTML_DIR]) + + dnl enable/disable documentation building + AC_ARG_ENABLE([gtk-doc], + AS_HELP_STRING([--enable-gtk-doc], + [use gtk-doc to build documentation [[default=no]]]),, + [enable_gtk_doc=no]) + + if test x$enable_gtk_doc = xyes; then + ifelse([$1],[], + [PKG_CHECK_EXISTS([gtk-doc],, + AC_MSG_ERROR([gtk-doc not installed and --enable-gtk-doc requested]))], + [PKG_CHECK_EXISTS([gtk-doc >= $1],, + AC_MSG_ERROR([You need to have gtk-doc >= $1 installed to build $PACKAGE_NAME]))]) + dnl don't check for glib if we build glib + if test "x$PACKAGE_NAME" != "xglib"; then + dnl don't fail if someone does not have glib + PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0,,) + fi + dnl don't rely on sed being pulled in implicitly. Fixes Solaris build. + if test -z "$SED"; then + AC_PROG_SED + fi + fi + + AC_MSG_CHECKING([whether to build gtk-doc documentation]) + AC_MSG_RESULT($enable_gtk_doc) + + dnl enable/disable output formats + AC_ARG_ENABLE([gtk-doc-html], + AS_HELP_STRING([--enable-gtk-doc-html], + [build documentation in html format [[default=yes]]]),, + [enable_gtk_doc_html=yes]) + AC_ARG_ENABLE([gtk-doc-pdf], + AS_HELP_STRING([--enable-gtk-doc-pdf], + [build documentation in pdf format [[default=no]]]),, + [enable_gtk_doc_pdf=no]) + + if test -z "$GTKDOC_MKPDF"; then + enable_gtk_doc_pdf=no + fi + + + AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes]) + AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes]) + AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes]) + AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"]) +]) diff --git a/common/m4/introspection.m4 b/common/m4/introspection.m4 new file mode 100644 index 0000000..589721c --- /dev/null +++ b/common/m4/introspection.m4 @@ -0,0 +1,94 @@ +dnl -*- mode: autoconf -*- +dnl Copyright 2009 Johan Dahlin +dnl +dnl This file is free software; the author(s) gives unlimited +dnl permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl + +# serial 1 + +m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], +[ + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([LT_INIT],[$0])dnl setup libtool first + + dnl enable/disable introspection + m4_if([$2], [require], + [dnl + enable_introspection=yes + ],[dnl + AC_ARG_ENABLE(introspection, + AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], + [Enable introspection for this build]),, + [enable_introspection=auto]) + ])dnl + + AC_MSG_CHECKING([for gobject-introspection]) + + dnl presence/version checking + AS_CASE([$enable_introspection], + [no], [dnl + found_introspection="no (disabled, use --enable-introspection to enable)" + ],dnl + [yes],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0],, + AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], + found_introspection=yes, + AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) + ],dnl + [auto],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) + ],dnl + [dnl + AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) + ])dnl + + AC_MSG_RESULT([$found_introspection]) + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + fi + AC_SUBST(INTROSPECTION_SCANNER) + AC_SUBST(INTROSPECTION_COMPILER) + AC_SUBST(INTROSPECTION_GENERATE) + AC_SUBST(INTROSPECTION_GIRDIR) + AC_SUBST(INTROSPECTION_TYPELIBDIR) + AC_SUBST(INTROSPECTION_CFLAGS) + AC_SUBST(INTROSPECTION_LIBS) + AC_SUBST(INTROSPECTION_MAKEFILE) + + AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") +]) + + +dnl Usage: +dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) + +AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) +]) + +dnl Usage: +dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) + + +AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) +]) diff --git a/common/m4/orc.m4 b/common/m4/orc.m4 new file mode 100644 index 0000000..26b2459 --- /dev/null +++ b/common/m4/orc.m4 @@ -0,0 +1,70 @@ +dnl pkg-config-based checks for Orc + +dnl specific: +dnl ORC_CHECK([REQUIRED_VERSION]) + +AC_DEFUN([ORC_CHECK], +[ + ORC_REQ=ifelse([$1], , "0.4.6", [$1]) + + AC_ARG_ENABLE(orc, + AC_HELP_STRING([--enable-orc],[use Orc if installed]), + [case "${enableval}" in + auto) enable_orc=auto ;; + yes) enable_orc=yes ;; + no) enable_orc=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-orc) ;; + esac + ], + [enable_orc=auto]) dnl Default value + + if test "x$enable_orc" != "xno" ; then + PKG_CHECK_MODULES(ORC, orc-0.4 >= $ORC_REQ, [ + AC_DEFINE(HAVE_ORC, 1, [Use Orc]) + HAVE_ORC=yes + if test "x$ORCC" = "x" ; then + AC_MSG_CHECKING(for usable orcc) + ORCC=`$PKG_CONFIG --variable=orcc orc-0.4` + dnl check whether the orcc found by pkg-config can be run from the build environment + dnl if this is not the case (e.g. when cross-compiling) fall back to orcc from PATH + AS_IF([$ORCC --version 1> /dev/null 2> /dev/null], [], [ORCC=`which orcc`]) + AC_MSG_RESULT($ORCC) + fi + AC_SUBST(ORCC) + ORCC_FLAGS="--compat $ORC_REQ" + AC_SUBST(ORCC_FLAGS) + AS_IF([test "x$ORCC" = "x"], [HAVE_ORCC=no], [HAVE_ORCC=yes]) + ], [ + if test "x$enable_orc" = "xyes" ; then + AC_MSG_ERROR([--enable-orc specified, but Orc >= $ORC_REQ not found]) + fi + AC_DEFINE(DISABLE_ORC, 1, [Disable Orc]) + HAVE_ORC=no + HAVE_ORCC=no + ]) + else + AC_DEFINE(DISABLE_ORC, 1, [Disable Orc]) + HAVE_ORC=no + HAVE_ORCC=no + fi + AM_CONDITIONAL(HAVE_ORC, [test "x$HAVE_ORC" = "xyes"]) + AM_CONDITIONAL(HAVE_ORCC, [test "x$HAVE_ORCC" = "xyes"]) + +])) + +AC_DEFUN([ORC_OUTPUT], +[ + if test "$HAVE_ORC" = yes ; then + printf "configure: *** Orc acceleration enabled.\n" + else + if test "x$enable_orc" = "xno" ; then + printf "configure: *** Orc acceleration disabled by --disable-orc. Slower code paths\n" + printf " will be used.\n" + else + printf "configure: *** Orc acceleration disabled. Requires Orc >= $ORC_REQ, which was\n" + printf " not found. Slower code paths will be used.\n" + fi + fi + printf "\n" +]) + diff --git a/common/m4/pkg.m4 b/common/m4/pkg.m4 new file mode 100644 index 0000000..996e294 --- /dev/null +++ b/common/m4/pkg.m4 @@ -0,0 +1,157 @@ +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# +# Copyright © 2004 Scott James Remnant . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi + +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# +# Similar to PKG_CHECK_MODULES, make sure that the first instance of +# this or PKG_CHECK_MODULES is called, or make sure to call +# PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_ifval([$2], [$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$PKG_CONFIG"; then + if test -n "$$1"; then + pkg_cv_[]$1="$$1" + else + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_failed=yes]) + fi +else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + ifelse([$4], , [AC_MSG_ERROR(dnl +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT +])], + [AC_MSG_RESULT([no]) + $4]) +elif test $pkg_failed = untried; then + ifelse([$4], , [AC_MSG_FAILURE(dnl +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])], + [$4]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + ifelse([$3], , :, [$3]) +fi[]dnl +])# PKG_CHECK_MODULES diff --git a/common/mangle-tmpl.py b/common/mangle-tmpl.py new file mode 100644 index 0000000..51ea8c2 --- /dev/null +++ b/common/mangle-tmpl.py @@ -0,0 +1,165 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +""" +use the output from gst-xmlinspect.py to mangle tmpl/*.sgml and +insert/overwrite Short Description and Long Description +""" + +# FIXME: right now it uses pygst and scans on its own; +# we really should use inspect/*.xml instead since the result of +# gst-xmlinspect.py is committed by the docs maintainer, who can be +# expected to have pygst, but this step should be done for every docs build, +# so no pygst allowed + +# read in inspect/*.xml +# for every tmpl/element-(name).xml: mangle with details from element + +from __future__ import print_function, unicode_literals + +import glob +import re +import sys +import os + +class Tmpl: + def __init__(self, filename): + self.filename = filename + self._sectionids = [] + self._sections = {} + + def read(self): + """ + Read and parse the sections from the given file. + """ + lines = open(self.filename).readlines() + matcher = re.compile("\n") + id = None + + for line in lines: + match = matcher.search(line) + if match: + id = match.expand("\\1") + self._sectionids.append(id) + self._sections[id] = [] + else: + if not id: + sys.stderr.write( + "WARNING: line before a SECTION header: %s" % line) + else: + self._sections[id].append(line) + + def get_section(self, id): + """ + Get the content from the given section. + """ + return self._sections[id] + + def set_section(self, id, content): + """ + Replace the given section id with the given content. + """ + self._sections[id] = content + + def output(self): + """ + Return the output of the current template in the tmpl/*.sgml format. + """ + lines = [] + for id in self._sectionids: + lines.append("\n" % id) + for line in self._sections[id]: + lines.append(line) + + return "".join(lines) + + def write(self, backup=False): + """ + Write out the template file again, backing up the previous one. + """ + if backup: + target = self.filename + ".mangle.bak" + os.rename(self.filename, target) + + handle = open(self.filename, "w") + handle.write(self.output()) + handle.close() + +import xml.dom.minidom + +def get_elements(file): + elements = {} + doc = xml.dom.minidom.parse(file) + + elem = None + for e in doc.childNodes: + if e.nodeType == e.ELEMENT_NODE and e.localName == 'plugin': + elem = e + break + if elem == None: + return None + + elem2 = None + for e in elem.childNodes: + if e.nodeType == e.ELEMENT_NODE and e.localName == 'elements': + elem2 = e + break + if elem2 == None: + return None + + elem = elem2 + + for e in elem.childNodes: + if e.nodeType == e.ELEMENT_NODE and e.localName == 'element': + name = None + description = None + + for e2 in e.childNodes: + if e2.nodeType == e2.ELEMENT_NODE and e2.localName == 'name': + name = e2.childNodes[0].nodeValue.encode("UTF-8") + elif e2.nodeType == e2.ELEMENT_NODE and e2.localName == 'description': + if e2.childNodes: + description = e2.childNodes[0].nodeValue.encode("UTF-8") + else: + description = 'No description' + + if name != None and description != None: + elements[name] = {'description': description} + + return elements + +def main(): + if not len(sys.argv) == 3: + sys.stderr.write('Please specify the inspect/ dir and the tmpl/ dir') + sys.exit(1) + + inspectdir = sys.argv[1] + tmpldir = sys.argv[2] + + # parse all .xml files; build map of element name -> short desc + #for file in glob.glob("inspect/plugin-*.xml"): + elements = {} + for file in glob.glob("%s/plugin-*.xml" % inspectdir): + elements.update(get_elements(file)) + + for file in glob.glob("%s/element-*.sgml" % tmpldir): + base = os.path.basename(file) + element = base[len("element-"):-len(".sgml")] + tmpl = Tmpl(file) + tmpl.read() + if element in elements.keys(): + description = elements[element]['description'] + tmpl.set_section("Short_Description", "%s\n\n" % description) + + # put in an include if not yet there + line = '' + \ + '' + \ + '\n' + section = tmpl.get_section("Long_Description") + if not section[0] == line: + section.insert(0, line) + tmpl.set_section("Long_Description", section) + tmpl.write() + +main() diff --git a/common/orc.mak b/common/orc.mak new file mode 100644 index 0000000..a232b5d --- /dev/null +++ b/common/orc.mak @@ -0,0 +1,76 @@ +# +# This is a makefile.am fragment to build Orc code. +# +# Define ORC_SOURCE and then include this file, such as: +# +# ORC_SOURCE=gstadderorc +# include $(top_srcdir)/common/orc.mak +# +# This fragment will create tmp-orc.c and gstadderorc.h from +# gstadderorc.orc. +# +# When 'make dist' is run at the top level, or 'make orc-update' +# in a directory including this fragment, the generated source +# files will be copied to $(ORC_SOURCE)-dist.[ch]. These files +# should be checked in to git, since they are used if Orc is +# disabled. +# +# Note that this file defines BUILT_SOURCES, so any later usage +# of BUILT_SOURCES in the Makefile.am that includes this file +# must use '+='. +# + + +EXTRA_DIST = $(ORC_SOURCE).orc + +ORC_NODIST_SOURCES = tmp-orc.c $(ORC_SOURCE).h +BUILT_SOURCES = tmp-orc.c $(ORC_SOURCE).h + + +orc-update: tmp-orc.c $(ORC_SOURCE).h + $(top_srcdir)/common/gst-indent tmp-orc.c + cp tmp-orc.c $(srcdir)/$(ORC_SOURCE)-dist.c + cp $(ORC_SOURCE).h $(srcdir)/$(ORC_SOURCE)-dist.h + +orcc_v_gen = $(orcc_v_gen_$(V)) +orcc_v_gen_ = $(orcc_v_gen_$(AM_DEFAULT_VERBOSITY)) +orcc_v_gen_0 = @echo " ORCC $@"; + +cp_v_gen = $(cp_v_gen_$(V)) +cp_v_gen_ = $(cp_v_gen_$(AM_DEFAULT_VERBOSITY)) +cp_v_gen_0 = @echo " CP $@"; + +if HAVE_ORCC +tmp-orc.c: $(srcdir)/$(ORC_SOURCE).orc + $(orcc_v_gen)$(ORCC) $(ORCC_FLAGS) --implementation --include glib.h -o tmp-orc.c $(srcdir)/$(ORC_SOURCE).orc + +$(ORC_SOURCE).h: $(srcdir)/$(ORC_SOURCE).orc + $(orcc_v_gen)$(ORCC) $(ORCC_FLAGS) --header --include glib.h -o $(ORC_SOURCE).h $(srcdir)/$(ORC_SOURCE).orc +else +tmp-orc.c: $(srcdir)/$(ORC_SOURCE).orc $(srcdir)/$(ORC_SOURCE)-dist.c + $(cp_v_gen)cp $(srcdir)/$(ORC_SOURCE)-dist.c tmp-orc.c + +$(ORC_SOURCE).h: $(srcdir)/$(ORC_SOURCE).orc $(srcdir)/$(ORC_SOURCE)-dist.c + $(cp_v_gen)cp $(srcdir)/$(ORC_SOURCE)-dist.h $(ORC_SOURCE).h +endif + +clean-local: clean-orc +.PHONY: clean-orc +clean-orc: + rm -f tmp-orc.c $(ORC_SOURCE).h + +dist-hook: dist-hook-orc +.PHONY: dist-hook-orc + +# we try and copy updated orc -dist files below, but don't fail if it +# doesn't work as the srcdir might not be writable +dist-hook-orc: tmp-orc.c $(ORC_SOURCE).h + $(top_srcdir)/common/gst-indent tmp-orc.c + rm -f tmp-orc.c~ + cmp -s tmp-orc.c $(srcdir)/$(ORC_SOURCE)-dist.c || \ + cp tmp-orc.c $(srcdir)/$(ORC_SOURCE)-dist.c || true + cmp -s $(ORC_SOURCE).h $(srcdir)/$(ORC_SOURCE)-dist.h || \ + cp $(ORC_SOURCE).h $(srcdir)/$(ORC_SOURCE)-dist.h || true + cp -p tmp-orc.c $(distdir)/$(ORC_SOURCE)-dist.c + cp -p $(ORC_SOURCE).h $(distdir)/$(ORC_SOURCE)-dist.h + diff --git a/common/parallel-subdirs.mak b/common/parallel-subdirs.mak new file mode 100644 index 0000000..36885df --- /dev/null +++ b/common/parallel-subdirs.mak @@ -0,0 +1,13 @@ +# include this at the end of $MODULE/ext/Makefile.am to force make to +# build subdirectories in parallel when make -jN is used. We will end up +# descending into all subdirectories a second time, but only after the first +# (parallel) run has finished, so it should go right through the second time. + +.PHONY: independent-subdirs $(SUBDIRS) + +independent-subdirs: $(SUBDIRS) + +$(SUBDIRS): + $(MAKE) -C $@ + +all-recursive: independent-subdirs diff --git a/common/plugins.xsl b/common/plugins.xsl new file mode 100644 index 0000000..60515b6 --- /dev/null +++ b/common/plugins.xsl @@ -0,0 +1,209 @@ + + + + + + + + + + + + -plugins- + + + + + + + + + + + + + + Element Information + + + + + plugin + + + + plugin- + + + + + + + + author + + + + + + + class + + + + + + + + + + Element Pads + + + + + name + + + + + + + direction + + + + + + + presence + + + + + + + + + details + + + + + + + + + + + + + + + + + + + + + -plugins-plugin- + + + + + + 3 + FIXME Library + + + + + + + + + + plugin- + + + + + + + Plugin Information + + + + filename + + + + + + + version + + + + + + + run-time license + + + + + + + package + + + + + + + origin + + + + + + + + + + + + + + + + + + + + + + + Elements + + + + + + + + + + + + + + diff --git a/common/po.mak b/common/po.mak new file mode 100644 index 0000000..e019fac --- /dev/null +++ b/common/po.mak @@ -0,0 +1,4 @@ +# rule to download the latest .po files +download-po: $(top_srcdir)/common/download-translations + $(top_srcdir)/common/download-translations $(PACKAGE) + diff --git a/common/release.mak b/common/release.mak new file mode 100644 index 0000000..715657b --- /dev/null +++ b/common/release.mak @@ -0,0 +1,34 @@ +# include this snippet to add a common release: target by using +# include $(top_srcdir)/common/release.mak + +release: dist + @$(MAKE) $(PACKAGE)-$(VERSION).tar.xz.sha256sum + @echo + @echo "=================================================================================================" + @echo "http://gstreamer.freedesktop.org/src/$(PACKAGE)/$(PACKAGE)-$(VERSION).tar.xz" + @cat $(PACKAGE)-$(VERSION).tar.xz.sha256sum + @echo "=================================================================================================" + @if [ -d ~/releases/ ]; then \ + cp -v $(PACKAGE)-$(VERSION).tar.xz ~/releases/; \ + fi + @if [ -d ../www/data/src ]; then \ + mv -v $(PACKAGE)-$(VERSION).tar.xz ../www/data/src/$(PACKAGE)/ ; \ + mv -v $(PACKAGE)-$(VERSION).tar.xz.sha256sum ../www/data/src/$(PACKAGE)/ ; \ + fi + @echo "=================================================================================================" + +# generate sha256 sum files +%.sha256sum: % + @sha256sum $< > $@ + +# check that no marshal or enumtypes files are included +# this in turn ensures that distcheck fails for missing .list files which is currently +# shadowed when the corresponding .c and .h files are included. +distcheck-hook: + @test "x" = "x`find $(distdir) -name \*-enumtypes.[ch] | grep -v win32`" && \ + test "x" = "x`find $(distdir) -name \*-marshal.[ch]`" || \ + ( echo "*** Leftover enumtypes or marshal files in the tarball." && \ + echo "*** Make sure the following files are not disted:" && \ + find $(distdir) -name \*-enumtypes.[ch] | grep -v win32 && \ + find $(distdir) -name \*-marshal.[ch] && \ + false ) diff --git a/common/scangobj-merge.py b/common/scangobj-merge.py new file mode 100755 index 0000000..4a9f1fc --- /dev/null +++ b/common/scangobj-merge.py @@ -0,0 +1,311 @@ +#!/usr/bin/python +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +""" +parse, merge and write gstdoc-scanobj files +""" + +from __future__ import print_function, unicode_literals + +import sys +import os + +def debug(*args): + pass + +# OrderedDict class based on +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747 +# Licensed under the Python License +class OrderedDict(dict): + def __init__(self): + self._keys = [] + dict.__init__(self) + + def __delitem__(self, key): + dict.__delitem__(self, key) + self._keys.remove(key) + + def __setitem__(self, key, item): + dict.__setitem__(self, key, item) + if key not in self._keys: self._keys.append(key) + + def clear(self): + dict.clear(self) + self._keys = [] + + def copy(self): + dict = dict.copy(self) + dict._keys = self._keys[:] + return dict + + def items(self): + return zip(self._keys, self.values()) + + def keys(self): + return self._keys + + def popitem(self): + try: + key = self._keys[-1] + except IndexError: + raise KeyError('dictionary is empty') + + val = self[key] + del self[key] + + return (key, val) + + def setdefault(self, key, failobj = None): + dict.setdefault(self, key, failobj) + if key not in self._keys: self._keys.append(key) + + def update(self, dict): + dict.update(self, dict) + for key in dict.keys(): + if key not in self._keys: self._keys.append(key) + + def values(self): + return map(self.get, self._keys) + +class Object: + def __init__(self, name): + self._signals = OrderedDict() + self._args = OrderedDict() + self.name = name + + def __repr__(self): + return "" % self.name + + def add_signal(self, signal, overwrite=True): + if not overwrite and signal.name in self._signals: + raise IndexError("signal %s already in %r" % (signal.name, self)) + self._signals[signal.name] = signal + + def add_arg(self, arg, overwrite=True): + if not overwrite and arg.name in self._args: + raise IndexError("arg %s already in %r" % (arg.name, self)) + self._args[arg.name] = arg + +class Docable: + def __init__(self, **kwargs): + for key in self.attrs: + setattr(self, key, kwargs[key]) + self.dict = kwargs + + def __repr__(self): + return "<%r %s>" % (str(self.__class__), self.name) + +class Signal(Docable): + attrs = ['name', 'returns', 'args'] + +class Arg(Docable): + attrs = ['name', 'type', 'range', 'flags', 'nick', 'blurb', 'default'] + +class GDoc: + def load_file(self, filename): + try: + lines = open(filename).readlines() + self.load_data("".join(lines)) + except IOError: + print ("WARNING - could not read from %s" % filename) + + def save_file(self, filename, backup=False): + """ + Save the information to the given file if the file content changed. + """ + olddata = None + try: + lines = open(filename).readlines() + olddata = "".join(lines) + except IOError: + print ("WARNING - could not read from %s" % filename) + newdata = self.get_data() + if olddata and olddata == newdata: + return + + if olddata: + if backup: + os.rename(filename, filename + '.bak') + + handle = open(filename, "w") + handle.write(newdata) + handle.close() + +class Signals(GDoc): + def __init__(self): + self._objects = OrderedDict() + + def load_data(self, data): + """ + Load the .signals lines, creating our list of objects and signals. + """ + import re + smatcher = re.compile( + '(?s)' # make . match \n + '\n(.*?)\n' + ) + nmatcher = re.compile( + '' + '(?P\S*)' # store object + '::' + '(?P\S*)' # store signal + '' + ) + rmatcher = re.compile( + '(?s)' # make . match \n + '(?P\S*)\n' # store returns + '(?P.*)' # store args + ) + for block in smatcher.findall(data): + nmatch = nmatcher.search(block) + if nmatch: + o = nmatch.group('object') + debug("Found object", o) + debug("Found signal", nmatch.group('signal')) + if o not in self._objects: + object = Object(o) + self._objects[o] = object + + rmatch = rmatcher.search(block) + if rmatch: + dict = rmatch.groupdict().copy() + dict['name'] = nmatch.group('signal') + signal = Signal(**dict) + self._objects[o].add_signal(signal) + + def get_data(self): + lines = [] + for o in self._objects.values(): + for s in o._signals.values(): + block = """ +%(object)s::%(name)s +%(returns)s +%(args)s +""" + d = s.dict.copy() + d['object'] = o.name + lines.append(block % d) + + return "\n".join(lines) + '\n' + +class Args(GDoc): + def __init__(self): + self._objects = OrderedDict() + + def load_data(self, data): + """ + Load the .args lines, creating our list of objects and args. + """ + import re + amatcher = re.compile( + '(?s)' # make . match \n + '\n(.*?)\n' + ) + nmatcher = re.compile( + '' + '(?P\S*)' # store object + '::' + '(?P\S*)' # store arg + '' + ) + rmatcher = re.compile( + '(?s)' # make . match \n + '(?P\S*)\n' # store type + '(?P.*?)\n' # store range + '(?P\S*)\n' # store flags + '(?P.*?)\n' # store nick + '(?P.*?)\n' # store blurb + '(?P.*?)\n' # store default + ) + for block in amatcher.findall(data): + nmatch = nmatcher.search(block) + if nmatch: + o = nmatch.group('object') + debug("Found object", o) + debug("Found arg", nmatch.group('arg')) + if o not in self._objects: + object = Object(o) + self._objects[o] = object + + rmatch = rmatcher.search(block) + if rmatch: + dict = rmatch.groupdict().copy() + dict['name'] = nmatch.group('arg') + arg = Arg(**dict) + self._objects[o].add_arg(arg) + else: + print ("ERROR: could not match arg from block %s" % block) + + def get_data(self): + lines = [] + for o in self._objects.values(): + for a in o._args.values(): + block = """ +%(object)s::%(name)s +%(type)s +%(range)s +%(flags)s +%(nick)s +%(blurb)s +%(default)s + +""" + d = a.dict.copy() + d['object'] = o.name + lines.append(block % d) + + return "\n".join(lines) + '\n' + +class SingleLine(GDoc): + def __init__(self): + self._objects = [] + + def load_data(self, data): + """ + Load the .interfaces/.prerequisites lines, merge duplicates + """ + # split data on '\n' + lines = data.splitlines(); + # merge them into self._objects + for line in lines: + if line not in self._objects: + self._objects.append(line) + + def get_data(self): + lines = sorted(self._objects) + return "\n".join(lines) + '\n' + +def main(argv): + modulename = None + try: + modulename = argv[1] + except IndexError: + sys.stderr.write('Please provide a documentation module name\n') + sys.exit(1) + + signals = Signals() + signals.load_file(modulename + '.signals') + signals.load_file(modulename + '.signals.new') + signals.save_file(modulename + '.signals', backup=True) + os.unlink(modulename + '.signals.new') + + args = Args() + args.load_file(modulename + '.args') + args.load_file(modulename + '.args.new') + args.save_file(modulename + '.args', backup=True) + os.unlink(modulename + '.args.new') + + ifaces = SingleLine() + ifaces.load_file(modulename + '.interfaces') + ifaces.load_file(modulename + '.interfaces.new') + ifaces.save_file(modulename + '.interfaces', backup=True) + os.unlink(modulename + '.interfaces.new') + + prereq = SingleLine() + prereq.load_file(modulename + '.prerequisites') + prereq.load_file(modulename + '.prerequisites.new') + prereq.save_file(modulename + '.prerequisites', backup=True) + os.unlink(modulename + '.prerequisites.new') + +main(sys.argv) diff --git a/common/upload-doc.mak b/common/upload-doc.mak new file mode 100644 index 0000000..c1c4945 --- /dev/null +++ b/common/upload-doc.mak @@ -0,0 +1,64 @@ +# this snippet is to be included by both our docbook manuals +# and gtk-doc API references + +# it adds an upload target to each of these dir's Makefiles + +# each Makefile.am should define the following variables: +# - DOC: the base name of the documentation +# (faq, manual, pwg, gstreamer, gstreamer-libs) +# - FORMATS: the formats in which DOC is output +# (html ps pdf) + +# if you want to use it, make sure your $HOME/.ssh/config file contains the +# correct User entry for the Host entry for the DOC_SERVER + +# these variables define the location of the online docs +DOC_SERVER = gstreamer.freedesktop.org +DOC_BASE = /srv/gstreamer.freedesktop.org/www/data/doc +DOC_URL = $(DOC_SERVER):$(DOC_BASE) + +upload: $(FORMATS) + @if echo $(FORMATS) | grep html > /dev/null; then \ + echo "Preparing docs for upload (rebasing cross-references) ..." ; \ + if test x$(builddir) != x$(srcdir); then \ + echo "make upload can only be used if srcdir == builddir"; \ + exit 1; \ + fi; \ + # gtkdoc-rebase sometimes gets confused, so reset everything to \ + # local links before rebasing to online links \ + gtkdoc-rebase --html-dir=$(builddir)/html 2>/dev/null 2>/dev/null ; \ + rebase=`gtkdoc-rebase --verbose --online --html-dir=$(builddir)/html` ; \ + echo "$$rebase" | grep -e "On-*line"; \ + for req in glib gobject gstreamer gstreamer-libs gst-plugins-base-libs; do \ + if ! ( echo "$$rebase" | grep -i -e "On-*line.*/$$req/" ); then \ + echo "===============================================================================" ; \ + echo " Could not determine online location for $$req docs. Cross-referencing will be " ; \ + echo " broken, so not uploading. Make sure the library's gtk-doc documentation is " ; \ + echo " installed somewhere in /usr/share/gtk-doc. " ; \ + echo "===============================================================================" ; \ + exit 1; \ + fi; \ + done; \ + export SRC="$$SRC html"; \ + fi; \ + if echo $(FORMATS) | grep ps > /dev/null; then export SRC="$$SRC $(DOC).ps"; fi; \ + if echo $(FORMATS) | grep pdf > /dev/null; then export SRC="$$SRC $(DOC).pdf"; fi; \ + \ + # upload releases to both X.Y/ and head/ subdirectories \ + export DIR=$(DOC_BASE)/gstreamer/$(PACKAGE_VERSION_MAJOR).$(PACKAGE_VERSION_MINOR)/$(DOC); \ + echo Uploading $$SRC to $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) mkdir -p $$DIR; \ + rsync -rv -e ssh --delete $$SRC $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) chmod -R g+w $$DIR; \ + \ + export DIR=$(DOC_BASE)/gstreamer/head/$(DOC); \ + echo Uploading $$SRC to $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) mkdir -p $$DIR; \ + rsync -rv -e ssh --delete $$SRC $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) chmod -R g+w $$DIR; \ + \ + if echo $(FORMATS) | grep html > /dev/null; then \ + echo "Un-preparing docs for upload (rebasing cross-references) ..." ; \ + gtkdoc-rebase --html-dir=$(builddir)/html ; \ + fi; \ + echo Done diff --git a/common/win32.mak b/common/win32.mak new file mode 100644 index 0000000..30e347e --- /dev/null +++ b/common/win32.mak @@ -0,0 +1,78 @@ +# various tests to make sure we dist the win32 stuff (for MSVC builds) right + +# the MANIFEST contains all win32 related files that should be disted +win32 = $(shell cat $(top_srcdir)/win32/MANIFEST) + +# wildcard is apparently not portable to other makes, hence the use of find +# these are library .def files with the symbols to export +win32defs = $(shell find $(top_srcdir)/win32/common -name '*.def') + +# wildcard is apparently not portable to other makes, hence the use of find +# these are files that need to be disted with CRLF line endings: +win32crlf = $(shell find $(top_srcdir)/win32 -name '*.dsw' -o -name '*.dsp') + +win32-debug: + @echo; \ + echo win32 = $(win32); \ + echo; \ + echo win32defs = $(win32defs); \ + echo; \ + echo win32crlf = $(win32crlf); \ + echo + +win32-check-crlf: + @echo Checking win32 files for CR LF line endings ...; \ + fail=0 ; \ + for each in $(win32crlf) ; do \ + result=`perl -e 'print grep(/\r\n/,<>)' "$$each" | wc -l`; \ + if test "$$result" = 0 ; then \ + echo $$each must be fixed to have CRLF line endings ; \ + fail=1; \ + fi ; \ + done ; \ + exit $$fail + +# make sure all symbols we export on linux are defined in the win32 .def too +# (don't care about other unixes for now, it's enough if it works on one of +# the linux build bots; we assume .so ) +check-exports: + @fail=0 ; \ + for l in $(win32defs); do \ + libbase=`basename "$$l" ".def"`; \ + libso=`find "$(top_builddir)" -name "$$libbase-@GST_API_VERSION@.so" | grep -v /_build/ | head -n1`; \ + libdef="$(top_srcdir)/win32/common/$$libbase.def"; \ + if test "x$$libso" != "x"; then \ + echo Checking symbols in $$libso; \ + if ! ($(top_srcdir)/common/check-exports $$libdef $$libso) ; then \ + fail=1; \ + fi; \ + fi; \ + done ; \ + if test $$fail != 0; then \ + echo '-----------------------------------------------------------'; \ + echo 'Run this to update the .def files:'; \ + echo 'make update-exports'; \ + echo '-----------------------------------------------------------'; \ + fi; \ + exit $$fail + +update-exports: + make check-exports 2>&1 | patch -p1 + git add win32/common/libgst*.def + git diff --cached -- win32/common/ + echo '^^^--- updated and staged changes above' + +# complain about nonportable printf format strings (%lld, %llu, %zu etc.) +check-nonportable-print-format: + @fail=0 ; \ + loc=`find "$(top_srcdir)" -name '*.c' | xargs grep -n -e '%[0-9]*ll[udx]' -e '%[0-9]*z[udx]'`; \ + if test "x$$loc" != "x"; then \ + echo "Please fix the following print format strings:" ; \ + find "$(top_srcdir)" -name '*.c' | xargs grep -n -e '%[0-9]*ll[udx]' -e '%[0-9]*z[udx]'; \ + fail=1; \ + fi; \ + exit $$fail + +dist-hook: check-exports win32-check-crlf + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..7a65c6f --- /dev/null +++ b/configure.ac @@ -0,0 +1,344 @@ +AC_PREREQ(2.62) +dnl initialize autoconf +dnl when going to/from release please set the nano (fourth number) right ! +dnl releases only do Wall, cvs and prerelease does Werror too +AC_INIT([GStreamer RTSP Server Library], [1.4.5], + [http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer], + [gst-rtsp-server]) +AG_GST_INIT + +dnl initialize automake +AM_INIT_AUTOMAKE([-Wno-portability 1.11 no-dist-gzip dist-xz tar-ustar subdir-objects]) + +dnl define PACKAGE_VERSION_* variables +AS_VERSION + +dnl check if this is a release version +AS_NANO(GST_GIT="no", GST_GIT="yes") + +dnl can autoconf find the source ? +AC_CONFIG_SRCDIR([gst/rtsp-server/rtsp-server.c]) + +dnl define the output header for config +AC_CONFIG_HEADERS([config.h]) + +dnl AM_MAINTAINER_MODE only provides the option to configure to enable it +AM_MAINTAINER_MODE([enable]) + +dnl sets host_* variables +AC_CANONICAL_HOST + +dnl use pretty build output with automake >= 1.11 +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])], + [AM_DEFAULT_VERBOSITY=1 + AC_SUBST(AM_DEFAULT_VERBOSITY)]) + +dnl our libraries and install dirs use major.minor as a version +dnl GST_API_VERSION=$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR +dnl we override it here if we need to for the release candidate of new series +GST_API_VERSION=1.0 +AC_SUBST(GST_API_VERSION) + +dnl CURRENT, REVISION, AGE +dnl - library source changed -> increment REVISION +dnl - interfaces added/removed/changed -> increment CURRENT, REVISION = 0 +dnl - interfaces added -> increment AGE +dnl - interfaces removed -> AGE = 0 +dnl +dnl Keep CURRENT as MINOR * 100 + MICRO +dnl Ex : 1.0.0 => 0 +dnl 1.0.3 => 3 +dnl 1.1.0 => 100 +dnl 1.2.5 => 205 +dnl 1.10.9 (who knows) => 1009 +dnl +dnl sets GST_LT_LDFLAGS +AS_LIBTOOL(GST, 405, 0, 405) + +dnl *** required versions of GStreamer stuff *** +GST_REQ=1.4.0 +GSTPB_REQ=1.4.0 +GSTPG_REQ=1.4.0 +GSTPD_REQ=1.4.0 + +dnl *** autotools stuff **** + +dnl allow for different autotools +AS_AUTOTOOLS_ALTERNATE + +dnl Add parameters for aclocal +AC_SUBST(ACLOCAL_AMFLAGS, "-I m4 -I common/m4") +AC_CONFIG_MACRO_DIR([m4]) + +dnl set up gettext +dnl the version check needs to stay here because autopoint greps for it +#AM_GNU_GETTEXT_VERSION([0.17]) +#AM_GNU_GETTEXT([external]) +#AG_GST_GETTEXT([gst-rtsp-server-$GST_API_VERSION]) + +dnl *** check for arguments to configure *** + +AG_GST_ARG_DISABLE_FATAL_WARNINGS + +AG_GST_ARG_DEBUG +AG_GST_ARG_VALGRIND +AG_GST_ARG_GCOV +AG_GST_ARG_WITH_PKG_CONFIG_PATH +AG_GST_ARG_WITH_PACKAGE_NAME +AG_GST_ARG_WITH_PACKAGE_ORIGIN + +AG_GST_PKG_CONFIG_PATH + +AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO([$PACKAGE_VERSION_NANO], + ["${srcdir}/gst-rtsp-server.doap"], + [$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR.$PACKAGE_VERSION_MICRO]) + +dnl building of tests +AC_ARG_ENABLE(tests, + AS_HELP_STRING([--disable-tests],[disable building test apps]), + [ + case "${enableval}" in + yes) BUILD_TESTS=yes ;; + no) BUILD_TESTS=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-tests) ;; + esac + ], +[BUILD_TESTS=yes]) dnl Default value +AM_CONDITIONAL(BUILD_TESTS, test "x$BUILD_TESTS" = "xyes") + +dnl *** checks for platform *** + +dnl * hardware/architecture * + +dnl *** checks for programs *** + +dnl find a compiler +AC_PROG_CC +AC_PROG_CC_STDC + +dnl check if the compiler supports '-c' and '-o' options +AM_PROG_CC_C_O + +dnl find an assembler +AM_PROG_AS + +AC_PATH_PROG(VALGRIND_PATH, valgrind, no) +AM_CONDITIONAL(HAVE_VALGRIND, test ! "x$VALGRIND_PATH" = "xno") + +dnl check for gobject-introspection +GOBJECT_INTROSPECTION_CHECK([1.31.1]) + +dnl check for documentation tools +AG_GST_DOCBOOK_CHECK +GTK_DOC_CHECK([1.12]) + +dnl *** checks for libraries *** + +dnl *** checks for header files *** + +dnl *** checks for types/defines *** + +dnl *** checks for structures *** + +dnl *** checks for compiler characteristics *** + +dnl *** checks for library functions *** + +dnl *** checks for dependancy libraries *** + +dnl GLib is required +GLIB_REQ=2.32.0 +AC_SUBST([GLIB_REQ]) +AG_GST_GLIB_CHECK([$GLIB_REQ]) + +dnl checks for gstreamer +dnl uninstalled is selected preferentially -- see pkg-config(1) +AG_GST_CHECK_GST($GST_API_VERSION, [$GST_REQ], [yes]) + +GST_TOOLS_DIR=`$PKG_CONFIG --variable=toolsdir gstreamer-$GST_API_VERSION` +if test -z $GST_TOOLS_DIR; then + AC_MSG_ERROR([no tools dir defined in GStreamer pkg-config file; core upgrade needed.]) +fi +AC_SUBST(GST_TOOLS_DIR) + +GST_PLUGINS_DIR=`$PKG_CONFIG gstreamer-$GST_API_VERSION --variable pluginsdir` +AC_SUBST(GST_PLUGINS_DIR) +AC_MSG_NOTICE(Using GStreamer Core Plugins in $GST_PLUGINS_DIR) + +AG_GST_CHECK_GST_BASE($GST_API_VERSION, [$GST_REQ], [yes]) + +AG_GST_CHECK_GST_PLUGINS_BASE($GST_API_VERSION, [$GSTPB_REQ], [yes]) +GSTPB_PLUGINS_DIR=`$PKG_CONFIG gstreamer-plugins-base-$GST_API_VERSION --variable pluginsdir` +AC_SUBST(GSTPB_PLUGINS_DIR) +AC_MSG_NOTICE(Using GStreamer Base Plugins in $GSTPB_PLUGINS_DIR) + +AG_GST_CHECK_GST_PLUGINS_GOOD($GST_API_VERSION, [$GSTPG_REQ], [yes]) +GSTPG_PLUGINS_DIR=`$PKG_CONFIG gstreamer-plugins-good-$GST_API_VERSION --variable pluginsdir` +AC_SUBST(GSTPG_PLUGINS_DIR) +AC_MSG_NOTICE(Using GStreamer Good Plugins in $GSTPG_PLUGINS_DIR) + +AG_GST_CHECK_GST_PLUGINS_BAD($GST_API_VERSION, [$GSTPD_REQ], [yes]) +GSTPD_PLUGINS_DIR=`$PKG_CONFIG gstreamer-plugins-bad-$GST_API_VERSION --variable pluginsdir` +AC_SUBST(GSTPD_PLUGINS_DIR) +AC_MSG_NOTICE(Using GStreamer Bad Plugins in $GSTPD_PLUGINS_DIR) + +AG_GST_CHECK_GST_CHECK($GST_API_VERSION, [$GST_REQ], no) +AM_CONDITIONAL(HAVE_CHECK, test "x$HAVE_GST_CHECK" = "xyes") + +dnl Check for -Bsymbolic-functions linker flag used to avoid +dnl intra-library PLT jumps, if available. +AC_ARG_ENABLE(Bsymbolic, + [AS_HELP_STRING([--disable-Bsymbolic],[avoid linking with -Bsymbolic])],, + [SAVED_LDFLAGS="${LDFLAGS}" + AC_MSG_CHECKING([for -Bsymbolic-functions linker flag]) + LDFLAGS=-Wl,-Bsymbolic-functions + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int main (void) { return 0; }]])],[ + AC_MSG_RESULT(yes) + enable_Bsymbolic=yes],[ + AC_MSG_RESULT(no) + enable_Bsymbolic=no]) + LDFLAGS="${SAVED_LDFLAGS}"]) + +dnl *** set variables based on configure arguments *** + +dnl set license and copyright notice +GST_LICENSE="LGPL" +AC_DEFINE_UNQUOTED(GST_LICENSE, "$GST_LICENSE", [GStreamer license]) +AC_SUBST(GST_LICENSE) + +dnl set location of plugin directory +AG_GST_SET_PLUGINDIR + +dnl set release date/time (and check that release version is in doap file) +AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO([$PACKAGE_VERSION_NANO], + ["${srcdir}/gst-rtsp-server.doap"], + [$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR.$PACKAGE_VERSION_MICRO]) + +# set by AG_GST_PARSE_SUBSYSTEM_DISABLES above +dnl make sure it doesn't complain about unused variables if debugging is disabled +NO_WARNINGS="" +AG_GST_CHECK_GST_DEBUG_DISABLED([NO_WARNINGS="-Wno-unused"], [NO_WARNINGS=""]) + +dnl define an ERROR_CFLAGS Makefile variable +AG_GST_SET_ERROR_CFLAGS($FATAL_WARNINGS, [-Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wundef -Wwrite-strings -Wformat-nonliteral -Wformat-security -Wold-style-definition -Winit-self -Wmissing-include-dirs -Waddress -Waggregate-return -Wno-multichar -Wnested-externs $NO_WARNINGS]) + +dnl define correct level for debugging messages +AG_GST_SET_LEVEL_DEFAULT($GST_GIT) + +dnl used in examples +AG_GST_DEFAULT_ELEMENTS + +dnl *** finalize CFLAGS, LDFLAGS, LIBS + +dnl Overview: +dnl GST_OPTION_CFLAGS: common flags for profiling, debugging, errors, ... +dnl GST_*: flags shared by built objects to link against GStreamer +dnl GST_ALL_LDFLAGS: linker flags shared by all +dnl GST_LIB_LDFLAGS: additional linker flags for all libaries +dnl GST_LT_LDFLAGS: library versioning of our libraries +dnl GST_PLUGIN_LDFLAGS: flags to be used for all plugins + +dnl GST_OPTION_CFLAGS +if test "x$USE_DEBUG" = xyes; then + PROFILE_CFLAGS="-g" +fi +AC_SUBST(PROFILE_CFLAGS) + +# GST_DISABLE_DEPRECATED: hide the visibility of deprecated +# functionality from the API that gstreamer uses +# GST_REMOVE_DEPRECATED: don't compile deprecated functionality (breaks ABI) +if test "x$PACKAGE_VERSION_NANO" = "x1"; then + dnl Define _only_ when compiling from git (not for pre-releases or releases) + DEPRECATED_CFLAGS="-DGST_DISABLE_DEPRECATED" +else + DEPRECATED_CFLAGS="" +fi +AC_SUBST(DEPRECATED_CFLAGS) + +dnl every flag in GST_OPTION_CFLAGS can be overridden at make time +GST_OPTION_CFLAGS="\$(WARNING_CFLAGS) \$(ERROR_CFLAGS) \$(DEBUG_CFLAGS) \$(PROFILE_CFLAGS) \$(GCOV_CFLAGS) \$(OPT_CFLAGS) \$(DEPRECATED_CFLAGS)" +AC_SUBST(GST_OPTION_CFLAGS) + +dnl FIXME: do we want to rename to GST_ALL_* ? +dnl prefer internal headers to already installed ones +dnl add GST_OPTION_CFLAGS, but overridable +GST_CFLAGS="$GST_CFLAGS \$(GST_OPTION_CFLAGS)" +AC_SUBST(GST_CFLAGS) +AC_SUBST(GST_LIBS) + +dnl GST_ALL_* +dnl vars common to for all internal objects (core libs, elements, applications) +dnl CFLAGS: +dnl - src and build dirs need to be added because every piece that gets built +dnl will need the GStreamer source and generated headers +GST_ALL_CFLAGS="-I\$(top_srcdir) -I\$(top_builddir) $GST_PLUGINS_BASE_CFLAGS $GST_CFLAGS \$(GST_OPTION_CFLAGS)" +AC_SUBST([GST_ALL_CFLAGS]) + +dnl FIXME: check if LTLIBINTL is needed everywhere +dnl I presume it is given that it contains the symbols that _() stuff maps to +GST_ALL_LIBS="$GST_LIBS $LTLIBINTL \$(GCOV_LIBS)" +AC_SUBST([GST_ALL_LIBS]) + +dnl LDFLAGS really should only contain flags, not libs - they get added before +dnl whatevertarget_LIBS and -L flags here affect the rest of the linking +GST_ALL_LDFLAGS="-no-undefined" +if test "x${enable_Bsymbolic}" = "xyes"; then + GST_ALL_LDFLAGS="$GST_ALL_LDFLAGS -Wl,-Bsymbolic-functions" +fi + +AC_SUBST(GST_ALL_LDFLAGS) + +dnl GST_LIB_LDFLAGS +dnl linker flags shared by all libraries +dnl LDFLAGS modifier defining exported symbols from built libraries +GST_LIB_LDFLAGS="-export-symbols-regex \^[_]?\(gst_\|Gst\|GST_\).*" +AC_SUBST(GST_LIB_LDFLAGS) + +dnl GST_OBJ_* +dnl default vars for all internal objects built on libgstrtspserver +dnl includes GST_ALL_* +GST_OBJ_CFLAGS="\$(GST_ALL_CFLAGS)" +AC_SUBST([GST_OBJ_CFLAGS]) +GST_OBJ_LIBS="\$(top_builddir)/gst/rtsp-server/libgstrtspserver-$GST_API_VERSION.la \$(GST_ALL_LIBS)" +AC_SUBST([GST_OBJ_LIBS]) + +PKG_CHECK_MODULES(LIBCGROUP, libcgroup >= 0.26, HAVE_LIBCGROUP="yes", HAVE_LIBCGROUP="no") +AC_SUBST(LIBCGROUP_CFLAGS) +AC_SUBST(LIBCGROUP_LIBS) +AM_CONDITIONAL(HAVE_LIBCGROUP, test "x$HAVE_LIBCGROUP" = "xyes") + +dnl this really should only contain flags, not libs - they get added before +dnl whatevertarget_LIBS and -L flags here affect the rest of the linking + +dnl *** output files *** + +dnl keep this alphabetic per directory, please +AC_CONFIG_FILES([ +Makefile +common/Makefile +common/m4/Makefile +gst/Makefile +gst/rtsp-server/Makefile +examples/Makefile +tests/Makefile +tests/check/Makefile +pkgconfig/Makefile +pkgconfig/gstreamer-rtsp-server.pc +pkgconfig/gstreamer-rtsp-server-uninstalled.pc +docs/Makefile +docs/version.entities +docs/libs/Makefile +]) +AC_OUTPUT + +echo " + +Configuration + Version : ${VERSION} + Source code location : ${srcdir} + Prefix : ${prefix} + Compiler : ${CC} + CGroups example : ${HAVE_LIBCGROUP} + +gst-rtsp-server configured. Type 'make' to build. +" diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000..9f9f150 --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1,20 @@ +if ENABLE_GTK_DOC +DOCS_SUBDIRS = libs +else +DOCS_SUBDIRS = +endif + +SUBDIRS = $(DOCS_SUBDIRS) +DIST_SUBDIRS = libs + +EXTRA_DIST = \ + version.entities.in + +upload: + @if test "x$(SUBDIRS)" != x; then \ + for a in $(SUBDIRS); do \ + cd $$a; \ + make upload; \ + cd ..; \ + done; \ + fi diff --git a/docs/Makefile.in b/docs/Makefile.in new file mode 100644 index 0000000..3aa1228 --- /dev/null +++ b/docs/Makefile.in @@ -0,0 +1,751 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = docs +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(srcdir)/version.entities.in README +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-docbook.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-default.m4 \ + $(top_srcdir)/common/m4/gst-doc.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = version.entities +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAT_ENTRY_END = @CAT_ENTRY_END@ +CAT_ENTRY_START = @CAT_ENTRY_START@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@ +DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@ +DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@ +DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@ +DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ = @GLIB_REQ@ +GREP = @GREP@ +GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@ +GSTPD_PLUGINS_DIR = @GSTPD_PLUGINS_DIR@ +GSTPG_PLUGINS_DIR = @GSTPG_PLUGINS_DIR@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_BASE_CFLAGS = @GST_BASE_CFLAGS@ +GST_BASE_LIBS = @GST_BASE_LIBS@ +GST_CFLAGS = @GST_CFLAGS@ +GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@ +GST_CHECK_LIBS = @GST_CHECK_LIBS@ +GST_CURRENT = @GST_CURRENT@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBS = @GST_LIBS@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGINS_BAD_CFLAGS = @GST_PLUGINS_BAD_CFLAGS@ +GST_PLUGINS_BAD_DIR = @GST_PLUGINS_BAD_DIR@ +GST_PLUGINS_BAD_LIBS = @GST_PLUGINS_BAD_LIBS@ +GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@ +GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@ +GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@ +GST_PLUGINS_DIR = @GST_PLUGINS_DIR@ +GST_PLUGINS_GOOD_CFLAGS = @GST_PLUGINS_GOOD_CFLAGS@ +GST_PLUGINS_GOOD_DIR = @GST_PLUGINS_GOOD_DIR@ +GST_PLUGINS_GOOD_LIBS = @GST_PLUGINS_GOOD_LIBS@ +GST_REVISION = @GST_REVISION@ +GST_TOOLS_DIR = @GST_TOOLS_DIR@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ +HAVE_DVIPS = @HAVE_DVIPS@ +HAVE_EPSTOPDF = @HAVE_EPSTOPDF@ +HAVE_JADETEX = @HAVE_JADETEX@ +HAVE_PNGTOPNM = @HAVE_PNGTOPNM@ +HAVE_PNMTOPS = @HAVE_PNMTOPS@ +HAVE_PS2PDF = @HAVE_PS2PDF@ +HAVE_XMLLINT = @HAVE_XMLLINT@ +HAVE_XSLTPROC = @HAVE_XSLTPROC@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCGROUP_CFLAGS = @LIBCGROUP_CFLAGS@ +LIBCGROUP_LIBS = @LIBCGROUP_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +XML_CATALOG = @XML_CATALOG@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@ENABLE_GTK_DOC_FALSE@DOCS_SUBDIRS = +@ENABLE_GTK_DOC_TRUE@DOCS_SUBDIRS = libs +SUBDIRS = $(DOCS_SUBDIRS) +DIST_SUBDIRS = libs +EXTRA_DIST = \ + version.entities.in + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu docs/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +version.entities: $(top_builddir)/config.status $(srcdir)/version.entities.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + + +upload: + @if test "x$(SUBDIRS)" != x; then \ + for a in $(SUBDIRS); do \ + cd $$a; \ + make upload; \ + cd ..; \ + done; \ + fi + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/docs/README b/docs/README new file mode 100644 index 0000000..e1cdc9c --- /dev/null +++ b/docs/README @@ -0,0 +1,498 @@ +README +------ + +(Last updated on Mon 15 jul 2013, version 0.11.90.1) + +This HOWTO describes the basic usage of the GStreamer RTSP libraries and how you +can build simple server applications with it. + +* General + + The server relies heavily on the RTSP infrastructure of GStreamer. This includes + all of the media acquisition, decoding, encoding, payloading and UDP/TCP + streaming. We use the rtpbin element for all the session management. Most of + the RTSP message parsing and construction in the server is done using the RTSP + library that comes with gst-plugins-base. + + The result is that the server is rather small (a few 11000 lines of code) and easy + to understand and extend. In its current state of development, things change + fast, API and ABI are unstable. We encourage people to use it for their various + use cases and participate by suggesting changes/features. + + Most of the server is built as a library containing a bunch of GObject objects + that provide reasonable default functionality but has a fair amount of hooks + to override the default behaviour. + + The server currently integrates with the glib mainloop nicely. It's currently + not meant to be used in high-load scenarios and because no security audit has + been done, you should probably not put it on a public IP address. + +* Initialisation + + You need to initialize GStreamer before using any of the RTSP server functions. + + #include + + int + main (int argc, char *argv[]) + { + gst_init (&argc, &argv); + + ... + } + + The server itself currently does not have any specific initialisation function + but that might change in the future. + + +* Creating the server + + The first thing you want to do is create a new GstRTSPServer object. This object + will handle all the new client connections to your server once it is added to a + GMainLoop. You can create a new server object like this: + + #include + + GstRTSPServer *server; + + server = gst_rtsp_server_new (); + + The server will by default listen on port 8554 for new connections. This can be + changed by calling gst_rtsp_server_set_service() or with the 'service' GObject + property. This makes it possible to run multiple server instances listening on + multiple ports on one machine. + + We can make the server start listening on its default port by attaching it to a + mainloop. The following example shows how this is done and will start a server + on the default 8554 port. For any request we make, we will get a NOT_FOUND + error code because we need to configure more things before the server becomes + useful. + + #include + #include + + int + main (int argc, char *argv[]) + { + GstRTSPServer *server; + GMainLoop *loop; + + gst_init (&argc, &argv); + + server = gst_rtsp_server_new (); + + /* make a mainloop for the default context */ + loop = g_main_loop_new (NULL, FALSE); + + /* attach the server to the default maincontext */ + gst_rtsp_server_attach (server, NULL); + + /* start serving */ + g_main_loop_run (loop); + } + + The server manages four other objects: GstRTSPSessionPool, + GstRTSPMountPoints, GstRTSPAuth and GstRTSPThreadPool. + + The GstRTSPSessionPool is an object that keeps track of all the active sessions + in the server. A session will usually be kept for each client that performed a + SETUP request for a certain media stream. It contains the configuration that + the client negotiated with the server to receive the particular stream, ie. the + transport used and port pairs for UDP along with the state of the streaming. + The default implementation of the session pool is usually sufficient but + alternative implementation can be used by the server. + + The GstRTSPMountPoints object is more interesting and needs more configuration + before the server object is useful. This object manages the mapping from a + request URL to a specific stream and its configuration. We explain in the next + topic how to configure this object. + + GstRTSPAuth is an object that authenticates users and authorizes actions + performed by users. By default, a server does not have a GstRTSPAuth object and + thus does not try to perform any authentication or authorization. + + GstRTSPThreadPool manages the threads used for client connections and media + pipelines. The server has a default implementation of a threadpool that should + be sufficient in most cases. + + +* Making url mount points + + Next we need to define what media is attached to a particular URL. What we want + to achieve is that when the user asks our server for a specific URL, say /test, + that we create (or reuse) a GStreamer pipeline that produces one or more RTP + streams. + + The object that can create such pipeline is called a GstRTSPMediaFactory object. + The default implementation of GstRTSPMediaFactory allows you to easily create + GStreamer pipelines using the gst-launch syntax. It is possible to create a + GstRTSPMediaFactory subclass that uses different methods for constructing + pipelines. + + The default GstRTSPMediaFactory can be configured with a gst-launch line that + produces a toplevel bin (use '(' and ')' around the pipeline description to + force a toplevel GstBin instead of the default GstPipeline toplevel element). + The pipeline description should contain elements named payN, one for each + stream (ex. pay0, pay1, ...). Also, for increased compatibility each stream + should have a different payload type which can be configured on the payloader. + + The following code snippet illustrates how to create a media factory that + creates an RTP feed of an H264 encoded test video signal. + + GstRTSPMediaFactory *factory; + + factory = gst_rtsp_media_factory_new (); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! x264enc ! rtph264pay pt=96 name=pay0 )"); + + Now that we have the media factory, we can attach it to a specific url. To do + this we get the default GstRTSPMountPoints from our server and add the url to + factory mount points to it like this: + + GstRTSPMountPoints *mounts; + + ...create server..create factory.. + + /* get the default mount points from the server */ + mounts = gst_rtsp_server_get_mount_points (server); + + /* attach the video test signal to the "/test" URL */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + g_object_unref (mounts); + + When starting the server now and directing an RTP client to the URL (like with + vlc, mplayer or gstreamer): + + rtsp://localhost:8554/test + + a test signal will be streamed to the client. The full example code can be + found in the examples/test-readme.c file. + + Note that by default the factory will create a new pipeline for each client. If + you want to share a pipeline between clients, use + gst_rtsp_media_factory_set_shared(). + + +* more on GstRTSPMediaFactory + + The GstRTSPMediaFactory is responsible for creating and caching GstRTSPMedia + objects. + + A freshly created GstRTSPMedia object from the factory initially only contains a + GstElement containing the elements to produce the RTP streams for the media and + a GPtrArray of GstRTSPStream objects describing the payloader and its source + pad. The media is unprepared in this state. + + Usually the url will determine what kind of pipeline should be created. You can + for example use query parameters to configure certain parts of the pipeline or + select encoders and payloaders based on some url pattern. + + When dealing with a live stream from, for example, a webcam, it can be + interesting to share the pipeline with multiple clients. This must be done when + only one instance of the video capture element can be used at a time. In this + case, the shared property of GstRTSPMedia must be used to instruct the default + GstRTSPMediaFactory implementation to cache the media. + + When all objects created from a factory can be shared, you can set the shared + property directly on the factory. + +* more on GstRTSPMedia + + After creating the GstRTSPMedia object from the factory, it can be prepared + with gst_rtsp_media_prepare(). This method will put those objects in a + GstPipeline and will construct and link the streaming elements and the + rtpbin session manager object. + + The _prepare() method will then preroll the pipeline in order to figure out the + caps on the payloaders. After the GstRTSPMedia prerolled it will be in the + prepared state and can be used for creating SDP files or for streaming to + clients. + + The prepare method will also create 2 UDP ports for each stream that can be + used for sending and receiving RTP/RTCP from clients. These port numbers will + have to be negotiated with the client in the SETUP requests. + + When preparing a GstRTSPMedia, an appsink and asppsrc is also constructed + for streaming the stream over TCP when requested. + + Media is prepared by the server when DESCRIBE or SETUP requests are received + from the client. + + +* the GstRTSPClient object + + When a server detects a new client connection on its port, it will accept the + connection, check if the connection is allowed and then call the vmethod + create_client. The default implementation of this function will create + a new GstRTCPClient object, will configure the session pool, mount points, + auth and thread pool objects in it. + + The server will then attach the new client to a server mainloop to let it + handle further communication with the client. In RTSP it is usual to keep + the connection open between multiple RTSP requests. The client watch will + be dispatched by the server mainloop when a new GstRTSPMessage is received, + which will then be handled and a response will be sent. + + The GstRTSPClient object remains alive for as long as a client has a TCP + connection open with the server. Since is possible for a client to open and close + the TCP connection between requests, we cannot store the state related + to the configured RTSP session in the GstRTSPClient object. This server state + is instead stored in the GstRTSPSession object, identified with the session + id. + + +* GstRTSPSession + + This object contains state about a specific RTSP session identified with a + session id. This state contains the configured streams and their associated + transports. + + When a GstRTSPClient performs a SETUP request, the server will allocate a new + GstRTSPSession with a unique session id from the GstRTSPSessionPool. The pool + maintains a list of all existing sessions and makes sure that no session id is + used multiple times. The session id is sent to the client so that the client + can refer to its previously configured state by sending the session id in + further requests. + + A client will then use the session id to configure one or more + GstRTSPSessionMedia objects, identified by their url. This SessionMedia object + contains the configuration of a GstRTSPMedia and its configured + GstRTSPStreamTransport. + + +* GstRTSPSessionMedia and GstRTSPStreamTransport + + A GstRTSPSessionMedia is identified by a URL and is referenced by a + GstRTSPSession. It is created as soon as a client performs a SETUP operation on + a particular URL. It will contain a link to the GstRTSPMedia object associated + with the URL along with the state of the media and the configured transports + for each of the streams in the media. + + Each SETUP request performed by the client will configure a + GstRTSPStreamTransport object linked to by the GstRTSPSessionMedia structure. + It will contain the transport information needed to send this stream to the + client. The GstRTSPStreamTransport also contains a link to the GstRTSPStream + object that generates the actual data to be streamed to the client. + + Note how GstRTSPMedia and GstRTSPStream (the providers of the data to + stream) are decoupled from GstRTSPSessionMedia and GstRTSPStreamTransport (the + configuration of how to send this stream to a client) in order to be able to + send the data of one GstRTSPMedia to multiple clients. + + +* media control + + After a client has configured the transports for a GstRTSPMedia and its + GstRTSPStreams, the client can play/pause/stop the stream. + + The GstRTSPMedia object was prepared in the DESCRIBE call (or during SETUP when + the client skipped the DESCRIBE request). As seen earlier, this configures a + couple of udpsink and udpsrc elements to respectively send and receive the + media to clients. + + When a client performs a PLAY request, its configured destination UDP ports are + added to the GstRTSPStream target destinations, at which point data will + be sent to the client. The corresponding GstRTSPMedia object will be set to the + PLAYING state if it was not allready in order to send the data to the + destination. + + The server needs to prepare an RTP-Info header field in the PLAY response, + which consists of the sequence number and the RTP timestamp of the next RTP + packet. In order to achive this, the server queries the payloaders for this + information when it prerolled the pipeline. + + When a client performs a PAUSE request, the destination UDP ports are removed + from the GstRTSPStream object and the GstRTSPMedia object is set to PAUSED + if no other destinations are configured anymore. + + +* seeking + + A seek is performed when a client sends a Range header in the PLAY request. + This only works when not dealing with shared (live) streams. + + The server performs a GStreamer flushing seek on the media, waits for the + pipeline to preroll again and then responds to the client after collecting the + new RTP sequence number and timestamp from the payloaders. + + +* session management + + The server has to react to clients that suddenly disappear because of network + problems or otherwise. It needs to make sure that it can reasonable free the + resources that are used by the various objects in use for streaming when the + client appears to be gone. + + Each of the GstRTSPSession objects managed by a GstRTSPSessionPool has + therefore a last_access field that contains the timestamp of when activity from + a client was last recorded. + + Various ways exist to detect activity from a client: + + - RTSP keepalive requests. When a client is receiving RTP data, the RTSP TCP + connection is largely unused. It is the client's responsability to + periodically send keep-alive requests over the TCP channel. + + Whenever a keep-alive request is received by the server (any request that + contains a session id, usually an OPTION or GET_PARAMETER request) the + last_access of the session is updated. + + - Since it is not required for a client to keep the RTSP TCP connection open + while streaming, gst-rtsp-server also detects activity from clients by + looking at the RTCP messages it receives. + + When an RTCP message is received from a client, the server looks in its list + of active ports if this message originates from a known host/port pair that + is currently active in a GstRTSPSession. If this is the case, the session is + kept alive. + + Since the server does not know anything about the port number that will be + used by the client to send RTCP, this method does not always work. Later + RTSP RFCs will include support for negotiating this port number with the + server. Most clients however use the same port number for sending and + receiving RTCP exactly for this reason. + + If there was no activity in a particular session for a long time (by default 60 + seconds), the application should remove the session from the pool. For this, + the application should periodically (say every 2 seconds) check if no sessions + expired and call gst_rtsp_session_pool_cleanup() to remove them. + + When a session is removed from the sessionpool and its last reference is + unreffef, all related objects and media are destroyed as if a TEARDOWN happened + from the client. + + +* TEARDOWN + + A TEARDOWN request will first locate the GstRTSPSessionMedia of the URL. It + will then remove all transports from the streams, making sure that streaming + stops to the clients. It will then remove the GstRTSPSessionMedia and + GstRTSPStreamTransport objects. Finally the GstRTSPSession is released back + into the pool. + + When there are no more references to the GstRTSPMedia, the media pipeline is + shut down (with _unprepare) and destroyed. This will then also destroy the + GstRTSPStream objects. + + +* Security + + The security of the server and the policy is implemented in a GstRTSPAuth + object. The object is reponsible for: + + - authenticate the user of the server. + + - check if the current user is authorized to perform an operation. + + For critical operations, the server will call gst_rtsp_auth_check() with + a string describing the operation which should be validated. The installed + GstRTSPAuth object is then responsible for checking if the operation is + allowed. + + Implementations of GstRTSPAuth objects can use the following infrastructure + bits of the rtsp server to implement these checks: + + - GstRTSPToken: a generic structure describing roles and permissions granted + to a user. + + - GstRTSPPermissions: a generic list of roles and matching permissions. These + can be attached to media and facties currently. + + An Auth implementation will usually authenticate a user, using method such as + Basic authentication or client certificates or perhaps simply use the IP address. + The result of the authentication of the user will be a GstRTSPToken that is made + current in the context of the ongoing request. + + The auth module can then implement the various checks in the server by looking + at the current token and, if needed, compare it to the required GstRTSPPermissions + of the current object. + + The security is deliberately kept generic with a default implementation of the + GstRTSPAuth object providing a usable and simple implementaion. To make more + complicated security modules, the auth object should be subclassed and new + implementations for the checks needs to be made. + + +Objects +------- + +GstRTSPServer + - Toplevel object listening for connections and creating new + GstRTSPClient objects + +GstRTSPClient + - Handle RTSP Requests from connected clients. All other objects + are called by this object. + +GstRTSPContext + - Helper structure contaning the current state of the request + handled by the client. + + +GstRTSPMountPoints + - Maps a url to a GstRTSPMediaFactory implementation. The default + implementation uses a simple hashtable to map a url to a factory. + +GstRTSPMediaFactory + - Creates and caches GstRTSPMedia objects. The default implementation + can create GstRTSPMedia objects based on gst-launch syntax. + +GstRTSPMediaFactoryURI + - Specialized GstRTSPMediaFactory that can stream the content of any + URI. + +GstRTSPMedia + - The object that contains the media pipeline and various GstRTSPStream + objects that produce RTP packets + +GstRTSPStream + - Manages the elements to stream a stream of a GstRTSPMedia to one or + more GstRTSPStreamTransports. + + +GstRTSPSessionPool + - Creates and manages GstRTSPSession objects identified by an id. + +GstRTSPSession + - An object containing the various GstRTSPSessionMedia objects managed + by this session. + +GstRTSPSessionMedia + - The state of a GstRTSPMedia and the configuration of a GstRTSPStream + objects. The configuration for the GstRTSPStream is stored in + GstRTSPStreamTransport objects. + +GstRTSPStreamTransport + - Configuration of how a GstRTSPStream is send to a particular client. It + contains the transport that was negotiated with the client in the SETUP + request. + + +GstRTSPSDP + - helper functions for creating SDP messages from gstRTSPMedia + +GstRTSPAddressPool + - a pool of multicast and unicast addresses used in streaming + +GstRTSPThreadPool + - a pool of threads used for various server tasks such as handling clients and + managin media pipelines. + + +GstRTSPAuth + - Hooks for checking authorizations, all client activity will call this + object with the GstRTSPContext structure. By default it supports + basic authentication. + +GstRTSPToken + - Credentials of a user. This contrains the roles that the user is allowed + to assume and other permissions or capabilities of the user. + +GstRTSPPermissions + - A list of permissions for each role. The permissions are usually attached + to objects to describe what roles have what permissions. + +GstRTSPParams + - object to handle get and set parameter requests. + diff --git a/docs/design/gst-rtp-server-design b/docs/design/gst-rtp-server-design new file mode 100644 index 0000000..7da8283 --- /dev/null +++ b/docs/design/gst-rtp-server-design @@ -0,0 +1,35 @@ +RTSP server +----------- + +This directory contains an example RTSP server built with various GStreamer +components and libraries. It also uses GStreamer for all of the multimedia +procesing and RTP bits. The following features are implemented: + + - + +Server Design +------------- + +The toplevel component of the server is a GstRTSPServer object. This object +creates and binds on the server socket and attaches into the mainloop. + +For each request a new GstRTSPClient object is created that will accept the +request and a thread is started to handle further communication with the +client until the connection is closed. + +When a client issues a SETUP request we create a GstRTSPSession object, +identified with a sessionid, that will keep track of the state of a client. +The object is destroyed when a TEARDOWN request is made for that sessionid. + +We also maintain a pool of URL to media pipeline mappings. Each url is mapped to +an object that is able to provide a pipeline for that media. We provide +pipelines to stream live captured data, on-demand file streaming or on-demand +transcoding of a file or stream. + +A pool of currently active pipelines is also maintained. Usually the active +pipelines are in use by one or more GstRTSPSession objects. An active pipeline +becomes inactive when no more sessions refer to it. + +A client can choose to start a new pipeline or join a currently active pipeline. +Some active pipeline cannot be joined (such as on-demand streams) but a new +instance of that pipeline can be created. diff --git a/docs/libs/Makefile.am b/docs/libs/Makefile.am new file mode 100644 index 0000000..64b7aa5 --- /dev/null +++ b/docs/libs/Makefile.am @@ -0,0 +1,106 @@ +GST_DOC_SCANOBJ = $(top_srcdir)/common/gstdoc-scangobj + +## Process this file with automake to produce Makefile.in + +# The name of the module, e.g. 'glib'. +MODULE=gst-rtsp-server +DOC_MODULE=$(MODULE) + +# for upload-doc.mak +DOC=$(MODULE) +FORMATS=html +html: html-build.stamp +include $(top_srcdir)/common/upload-doc.mak + +# generated basefiles +#basefiles = \ +## $(DOC_MODULE).types \ +# $(DOC_MODULE)-sections.txt \ +# $(DOC_MODULE)-docs.sgml + +# ugly hack to make -unused.sgml work +#unused-build.stamp: +# BUILDDIR=`pwd` && \ +# cd $(srcdir)/tmpl && \ +# ln -sf gstreamer-libs-unused.sgml \ +# $$BUILDDIR/tmpl/gstreamer-libs-@GST_API_VERSION@-unused.sgml +# touch unused-build.stamp + +# these rules are added to create parallel docs using GST_API_VERSION +#$(basefiles): gstreamer-libs-@GST_API_VERSION@%: gstreamer-libs% +# cp $< $@ + +#CLEANFILES = $(basefiles) + +# The top-level SGML file. Change it if you want. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The directory containing the source code. Relative to $(top_srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting functions and macros. +DOC_SOURCE_DIR = $(top_srcdir)/gst/rtsp-server/ +DOC_BUILD_DIR=$(top_builddir)/gst/rtsp-server/ + +SCAN_OPTIONS= + +# FIXME : +# there's something wrong with gstreamer-sections.txt not being in the dist +# maybe it doesn't resolve; we're adding it below for now +#EXTRA_DIST = gstreamer.types.in gstreamer.hierarchy $(DOC_MODULE)-sections.txt gstreamer-sections.txt $(DOC_MAIN_SGML_FILE) + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS=--sgml-mode --source-suffixes=c,h,cc,m + +# Extra options to supply to gtkdoc-fixref. +FIXXREF_OPTIONS=--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \ + --extra-dir=$(GST_PREFIX)/share/gtk-doc/html \ + --extra-dir=$(GSTPB_PREFIX)/share/gtk-doc/html + +# Used for dependencies. +HFILE_GLOB=$(DOC_SOURCE_DIR)/*.h +CFILE_GLOB=$(DOC_SOURCE_DIR)/*.c + +SCANOBJ_DEPS = \ + $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la + +# Extra options to supply to gtkdoc-scan. +SCANOBJ_OPTIONS=--type-init-func="g_type_init();gst_init(&argc,&argv)" + +# Header files to ignore when scanning. +IGNORE_HFILES = +IGNORE_CFILES = + +# we add all .h files of elements that have signals/args we want +# sadly this also pulls in the private methods - maybe we should +# move those around in the source ? +# also, we should add some stuff here conditionally based on whether +# or not the plugin will actually build +# but I'm not sure about that - it might be this Just Works given that +# the registry won't have the element + +EXTRA_HFILES = + +# Images to copy into HTML directory. +HTML_IMAGES = + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +content_files = + +# Other files to distribute. +extra_files = + +# CFLAGS and LDFLAGS for compiling scan program. Only needed if your app/lib +# contains GtkObjects/GObjects and you want to document signals and properties. +GTKDOC_CFLAGS = -I$(top_srcdir) $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CFLAGS) +GTKDOC_LIBS = $(SCANOBJ_DEPS) $(GST_PLUGINS_BASE_LIBS) \ + $(GST_BASE_LIBS) $(GST_LIBS) $(GCOV_LIBS) + +GTKDOC_CC=$(LIBTOOL) --tag=CC --mode=compile $(CC) +GTKDOC_LD=$(LIBTOOL) --tag=CC --mode=link $(CC) + +# If you need to override some of the declarations, place them in this file +# and uncomment this line. +DOC_OVERRIDES = $(DOC_MODULE)-overrides.txt + +include $(top_srcdir)/common/gtk-doc.mak diff --git a/docs/libs/Makefile.in b/docs/libs/Makefile.in new file mode 100644 index 0000000..95811a2 --- /dev/null +++ b/docs/libs/Makefile.in @@ -0,0 +1,946 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# this snippet is to be included by both our docbook manuals +# and gtk-doc API references + +# it adds an upload target to each of these dir's Makefiles + +# each Makefile.am should define the following variables: +# - DOC: the base name of the documentation +# (faq, manual, pwg, gstreamer, gstreamer-libs) +# - FORMATS: the formats in which DOC is output +# (html ps pdf) + +# if you want to use it, make sure your $HOME/.ssh/config file contains the +# correct User entry for the Host entry for the DOC_SERVER + +########################################################################### +# Everything below here is generic and you shouldn't need to change it. +########################################################################### +# thomas: except of course that we did +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +DIST_COMMON = $(top_srcdir)/common/upload-doc.mak \ + $(top_srcdir)/common/gtk-doc.mak $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.am +subdir = docs/libs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-docbook.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-default.m4 \ + $(top_srcdir)/common/m4/gst-doc.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAT_ENTRY_END = @CAT_ENTRY_END@ +CAT_ENTRY_START = @CAT_ENTRY_START@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@ +DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@ +DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@ +DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@ +DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ = @GLIB_REQ@ +GREP = @GREP@ +GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@ +GSTPD_PLUGINS_DIR = @GSTPD_PLUGINS_DIR@ +GSTPG_PLUGINS_DIR = @GSTPG_PLUGINS_DIR@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_BASE_CFLAGS = @GST_BASE_CFLAGS@ +GST_BASE_LIBS = @GST_BASE_LIBS@ +GST_CFLAGS = @GST_CFLAGS@ +GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@ +GST_CHECK_LIBS = @GST_CHECK_LIBS@ +GST_CURRENT = @GST_CURRENT@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBS = @GST_LIBS@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGINS_BAD_CFLAGS = @GST_PLUGINS_BAD_CFLAGS@ +GST_PLUGINS_BAD_DIR = @GST_PLUGINS_BAD_DIR@ +GST_PLUGINS_BAD_LIBS = @GST_PLUGINS_BAD_LIBS@ +GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@ +GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@ +GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@ +GST_PLUGINS_DIR = @GST_PLUGINS_DIR@ +GST_PLUGINS_GOOD_CFLAGS = @GST_PLUGINS_GOOD_CFLAGS@ +GST_PLUGINS_GOOD_DIR = @GST_PLUGINS_GOOD_DIR@ +GST_PLUGINS_GOOD_LIBS = @GST_PLUGINS_GOOD_LIBS@ +GST_REVISION = @GST_REVISION@ +GST_TOOLS_DIR = @GST_TOOLS_DIR@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ +HAVE_DVIPS = @HAVE_DVIPS@ +HAVE_EPSTOPDF = @HAVE_EPSTOPDF@ +HAVE_JADETEX = @HAVE_JADETEX@ +HAVE_PNGTOPNM = @HAVE_PNGTOPNM@ +HAVE_PNMTOPS = @HAVE_PNMTOPS@ +HAVE_PS2PDF = @HAVE_PS2PDF@ +HAVE_XMLLINT = @HAVE_XMLLINT@ +HAVE_XSLTPROC = @HAVE_XSLTPROC@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCGROUP_CFLAGS = @LIBCGROUP_CFLAGS@ +LIBCGROUP_LIBS = @LIBCGROUP_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +XML_CATALOG = @XML_CATALOG@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +GST_DOC_SCANOBJ = $(top_srcdir)/common/gstdoc-scangobj + +# The name of the module, e.g. 'glib'. +MODULE = gst-rtsp-server +DOC_MODULE = $(MODULE) + +# for upload-doc.mak +DOC = $(MODULE) +FORMATS = html + +# these variables define the location of the online docs +DOC_SERVER = gstreamer.freedesktop.org +DOC_BASE = /srv/gstreamer.freedesktop.org/www/data/doc +DOC_URL = $(DOC_SERVER):$(DOC_BASE) + +# generated basefiles +#basefiles = \ +# $(DOC_MODULE)-sections.txt \ +# $(DOC_MODULE)-docs.sgml + +# ugly hack to make -unused.sgml work +#unused-build.stamp: +# BUILDDIR=`pwd` && \ +# cd $(srcdir)/tmpl && \ +# ln -sf gstreamer-libs-unused.sgml \ +# $$BUILDDIR/tmpl/gstreamer-libs-@GST_API_VERSION@-unused.sgml +# touch unused-build.stamp + +# these rules are added to create parallel docs using GST_API_VERSION +#$(basefiles): gstreamer-libs-@GST_API_VERSION@%: gstreamer-libs% +# cp $< $@ + +#CLEANFILES = $(basefiles) + +# The top-level SGML file. Change it if you want. +DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.sgml + +# The directory containing the source code. Relative to $(top_srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting functions and macros. +DOC_SOURCE_DIR = $(top_srcdir)/gst/rtsp-server/ +DOC_BUILD_DIR = $(top_builddir)/gst/rtsp-server/ +SCAN_OPTIONS = + +# FIXME : +# there's something wrong with gstreamer-sections.txt not being in the dist +# maybe it doesn't resolve; we're adding it below for now +#EXTRA_DIST = gstreamer.types.in gstreamer.hierarchy $(DOC_MODULE)-sections.txt gstreamer-sections.txt $(DOC_MAIN_SGML_FILE) + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS = --sgml-mode --source-suffixes=c,h,cc,m + +# Extra options to supply to gtkdoc-fixref. +FIXXREF_OPTIONS = --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \ + --extra-dir=$(GST_PREFIX)/share/gtk-doc/html \ + --extra-dir=$(GSTPB_PREFIX)/share/gtk-doc/html + + +# Used for dependencies. +HFILE_GLOB = $(DOC_SOURCE_DIR)/*.h +CFILE_GLOB = $(DOC_SOURCE_DIR)/*.c +SCANOBJ_DEPS = \ + $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la + + +# Extra options to supply to gtkdoc-scan. +SCANOBJ_OPTIONS = --type-init-func="g_type_init();gst_init(&argc,&argv)" + +# Header files to ignore when scanning. +IGNORE_HFILES = +IGNORE_CFILES = + +# we add all .h files of elements that have signals/args we want +# sadly this also pulls in the private methods - maybe we should +# move those around in the source ? +# also, we should add some stuff here conditionally based on whether +# or not the plugin will actually build +# but I'm not sure about that - it might be this Just Works given that +# the registry won't have the element +EXTRA_HFILES = + +# Images to copy into HTML directory. +HTML_IMAGES = + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +content_files = + +# Other files to distribute. +extra_files = + +# CFLAGS and LDFLAGS for compiling scan program. Only needed if your app/lib +# contains GtkObjects/GObjects and you want to document signals and properties. +GTKDOC_CFLAGS = -I$(top_srcdir) $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CFLAGS) + +GTKDOC_LIBS = $(SCANOBJ_DEPS) $(GST_PLUGINS_BASE_LIBS) \ + $(GST_BASE_LIBS) $(GST_LIBS) $(GCOV_LIBS) + +GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) +GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) + +# If you need to override some of the declarations, place them in this file +# and uncomment this line. +DOC_OVERRIDES = $(DOC_MODULE)-overrides.txt + +# thomas: copied from glib-2 +# We set GPATH here; this gives us semantics for GNU make +# which are more like other make's VPATH, when it comes to +# whether a source that is a target of one rule is then +# searched for in VPATH/GPATH. +# +GPATH = $(srcdir) + +# thomas: make docs parallel installable +TARGET_DIR = $(HTML_DIR)/$(DOC_MODULE)-@GST_API_VERSION@ +EXTRA_DIST = \ + $(content_files) \ + $(extra_files) \ + $(HTML_IMAGES) \ + $(DOC_MAIN_SGML_FILE) \ + $(DOC_MODULE).types \ + $(DOC_OVERRIDES) \ + $(DOC_MODULE)-sections.txt + +DOC_STAMPS = \ + setup-build.stamp \ + scan-build.stamp \ + sgml-build.stamp \ + html-build.stamp \ + sgml.stamp \ + html.stamp + +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals \ + .libs/$(DOC_MODULE)-scan.o + +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) doc-registry.xml +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common/upload-doc.mak $(top_srcdir)/common/gtk-doc.mak $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/libs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu docs/libs/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/common/upload-doc.mak $(top_srcdir)/common/gtk-doc.mak: + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +all-am: Makefile all-local +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-local + +dvi: dvi-am + +dvi-am: + +html-am: + +info: info-am + +info-am: + +install-data-am: install-data-local + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic \ + maintainer-clean-local + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-local + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool clean-local cscopelist-am ctags-am dist-hook \ + distclean distclean-generic distclean-libtool distclean-local \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-data-local \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + maintainer-clean-local mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-local + +html: html-build.stamp + +upload: $(FORMATS) + @if echo $(FORMATS) | grep html > /dev/null; then \ + echo "Preparing docs for upload (rebasing cross-references) ..." ; \ + if test x$(builddir) != x$(srcdir); then \ + echo "make upload can only be used if srcdir == builddir"; \ + exit 1; \ + fi; \ + # gtkdoc-rebase sometimes gets confused, so reset everything to \ + # local links before rebasing to online links \ + gtkdoc-rebase --html-dir=$(builddir)/html 2>/dev/null 2>/dev/null ; \ + rebase=`gtkdoc-rebase --verbose --online --html-dir=$(builddir)/html` ; \ + echo "$$rebase" | grep -e "On-*line"; \ + for req in glib gobject gstreamer gstreamer-libs gst-plugins-base-libs; do \ + if ! ( echo "$$rebase" | grep -i -e "On-*line.*/$$req/" ); then \ + echo "===============================================================================" ; \ + echo " Could not determine online location for $$req docs. Cross-referencing will be " ; \ + echo " broken, so not uploading. Make sure the library's gtk-doc documentation is " ; \ + echo " installed somewhere in /usr/share/gtk-doc. " ; \ + echo "===============================================================================" ; \ + exit 1; \ + fi; \ + done; \ + export SRC="$$SRC html"; \ + fi; \ + if echo $(FORMATS) | grep ps > /dev/null; then export SRC="$$SRC $(DOC).ps"; fi; \ + if echo $(FORMATS) | grep pdf > /dev/null; then export SRC="$$SRC $(DOC).pdf"; fi; \ + \ + # upload releases to both X.Y/ and head/ subdirectories \ + export DIR=$(DOC_BASE)/gstreamer/$(PACKAGE_VERSION_MAJOR).$(PACKAGE_VERSION_MINOR)/$(DOC); \ + echo Uploading $$SRC to $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) mkdir -p $$DIR; \ + rsync -rv -e ssh --delete $$SRC $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) chmod -R g+w $$DIR; \ + \ + export DIR=$(DOC_BASE)/gstreamer/head/$(DOC); \ + echo Uploading $$SRC to $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) mkdir -p $$DIR; \ + rsync -rv -e ssh --delete $$SRC $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) chmod -R g+w $$DIR; \ + \ + if echo $(FORMATS) | grep html > /dev/null; then \ + echo "Un-preparing docs for upload (rebasing cross-references) ..." ; \ + gtkdoc-rebase --html-dir=$(builddir)/html ; \ + fi; \ + echo Done + +@ENABLE_GTK_DOC_TRUE@all-local: html-build.stamp + +#### setup #### + +@ENABLE_GTK_DOC_TRUE@setup-build.stamp: $(content_files) +@ENABLE_GTK_DOC_TRUE@ -@if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ +@ENABLE_GTK_DOC_TRUE@ echo ' DOC Preparing build'; \ +@ENABLE_GTK_DOC_TRUE@ files=`echo $(DOC_MAIN_SGML_FILE) $(DOC_OVERRIDES) $(DOC_MODULE)-sections.txt $(DOC_MODULE).types $(content_files)`; \ +@ENABLE_GTK_DOC_TRUE@ if test "x$$files" != "x" ; then \ +@ENABLE_GTK_DOC_TRUE@ for file in $$files ; do \ +@ENABLE_GTK_DOC_TRUE@ test -f $(abs_srcdir)/$$file && \ +@ENABLE_GTK_DOC_TRUE@ cp -pu $(abs_srcdir)/$$file $(abs_builddir)/ || true; \ +@ENABLE_GTK_DOC_TRUE@ done; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ fi +@ENABLE_GTK_DOC_TRUE@ @touch setup-build.stamp + +#### scan #### + +# in the case of non-srcdir builds, the built gst directory gets added +# to gtk-doc scanning; but only then, to avoid duplicates +@ENABLE_GTK_DOC_TRUE@scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Scanning header files' +@ENABLE_GTK_DOC_TRUE@ @_source_dir='' ; \ +@ENABLE_GTK_DOC_TRUE@ for i in $(DOC_SOURCE_DIR) ; do \ +@ENABLE_GTK_DOC_TRUE@ _source_dir="$${_source_dir} --source-dir=$$i" ; \ +@ENABLE_GTK_DOC_TRUE@ done ; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-scan \ +@ENABLE_GTK_DOC_TRUE@ $(SCAN_OPTIONS) $(EXTRA_HFILES) \ +@ENABLE_GTK_DOC_TRUE@ --module=$(DOC_MODULE) \ +@ENABLE_GTK_DOC_TRUE@ $${_source_dir} \ +@ENABLE_GTK_DOC_TRUE@ --ignore-headers="$(IGNORE_HFILES)" +@ENABLE_GTK_DOC_TRUE@ @if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null; then \ +@ENABLE_GTK_DOC_TRUE@ echo " DOC Introspecting gobjects"; \ +@ENABLE_GTK_DOC_TRUE@ GST_PLUGIN_SYSTEM_PATH_1_0=`cd $(top_builddir) && pwd` \ +@ENABLE_GTK_DOC_TRUE@ GST_PLUGIN_PATH_1_0= \ +@ENABLE_GTK_DOC_TRUE@ GST_REGISTRY_1_0=doc-registry.xml \ +@ENABLE_GTK_DOC_TRUE@ $(GTKDOC_EXTRA_ENVIRONMENT) \ +@ENABLE_GTK_DOC_TRUE@ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" \ +@ENABLE_GTK_DOC_TRUE@ CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" \ +@ENABLE_GTK_DOC_TRUE@ LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-scangobj --type-init-func="gst_init(NULL,NULL)" \ +@ENABLE_GTK_DOC_TRUE@ --module=$(DOC_MODULE) ; \ +@ENABLE_GTK_DOC_TRUE@ else \ +@ENABLE_GTK_DOC_TRUE@ for i in $(SCANOBJ_FILES) ; do \ +@ENABLE_GTK_DOC_TRUE@ test -f $$i || touch $$i ; \ +@ENABLE_GTK_DOC_TRUE@ done \ +@ENABLE_GTK_DOC_TRUE@ fi +@ENABLE_GTK_DOC_TRUE@ @touch scan-build.stamp + +@ENABLE_GTK_DOC_TRUE@$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp +@ENABLE_GTK_DOC_TRUE@ @true + +#### xml #### + +@ENABLE_GTK_DOC_TRUE@sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(expand_content_files) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Building XML' +@ENABLE_GTK_DOC_TRUE@ @gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) --output-format=xml $(MKDB_OPTIONS) +@ENABLE_GTK_DOC_TRUE@ @cp ../version.entities xml +@ENABLE_GTK_DOC_TRUE@ @touch sgml-build.stamp + +@ENABLE_GTK_DOC_TRUE@sgml.stamp: sgml-build.stamp +@ENABLE_GTK_DOC_TRUE@ @true + +#### html #### + +@ENABLE_GTK_DOC_TRUE@html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Building HTML' +@ENABLE_GTK_DOC_TRUE@ @rm -rf html +@ENABLE_GTK_DOC_TRUE@ @mkdir html +@ENABLE_GTK_DOC_TRUE@ @cp -pr xml html +@ENABLE_GTK_DOC_TRUE@ @cp ../version.entities ./ +@ENABLE_GTK_DOC_TRUE@ @mkhtml_options=""; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ +@ENABLE_GTK_DOC_TRUE@ if test "$(?)" = "0"; then \ +@ENABLE_GTK_DOC_TRUE@ if test "x$(V)" = "x1"; then \ +@ENABLE_GTK_DOC_TRUE@ mkhtml_options="$$mkhtml_options --verbose"; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ @gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ +@ENABLE_GTK_DOC_TRUE@ if test "$(?)" = "0"; then \ +@ENABLE_GTK_DOC_TRUE@ mkhtml_options=--path="$(abs_srcdir)"; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE)-@GST_API_VERSION@ ../$(DOC_MAIN_SGML_FILE) +@ENABLE_GTK_DOC_TRUE@ @rm -rf html/xml +@ENABLE_GTK_DOC_TRUE@ @rm -f version.entities +@ENABLE_GTK_DOC_TRUE@ @test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) $(abs_builddir)/html ) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Fixing cross-references' +@ENABLE_GTK_DOC_TRUE@ @gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) +@ENABLE_GTK_DOC_TRUE@ @touch html-build.stamp + +@ENABLE_GTK_DOC_TRUE@clean-local-gtkdoc: +@ENABLE_GTK_DOC_TRUE@ @rm -rf xml tmpl html +# clean files copied for nonsrcdir templates build +@ENABLE_GTK_DOC_TRUE@ @if test x"$(srcdir)" != x. ; then \ +@ENABLE_GTK_DOC_TRUE@ rm -rf $(DOC_MODULE).types; \ +@ENABLE_GTK_DOC_TRUE@ fi +@ENABLE_GTK_DOC_FALSE@all-local: +@ENABLE_GTK_DOC_FALSE@clean-local-gtkdoc: + +clean-local: clean-local-gtkdoc + @rm -f *~ *.bak + @rm -rf .libs + +distclean-local: + @rm -f $(REPORT_FILES) \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + @rm -rf tmpl/*.sgml.bak + @rm -f $(DOC_MODULE).hierarchy + @rm -f *.stamp || true + @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + rm -f $(DOC_MAIN_SGML_FILE) ; \ + rm -f $(DOC_OVERRIDES) ; \ + rm -f $(DOC_MODULE).types ; \ + rm -f $(DOC_MODULE).interfaces ; \ + rm -f $(DOC_MODULE).prerequisites ; \ + rm -f $(DOC_MODULE)-sections.txt ; \ + rm -f $(content_files) ; \ + rm -rf tmpl/*.sgml ; \ + fi + @rm -rf *.o + +maintainer-clean-local: clean + @cd $(srcdir) && rm -rf html \ + xml $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + +# thomas: make docs parallel installable; devhelp requires majorminor too +install-data-local: + (installfiles=`echo $(builddir)/html/*.sgml $(builddir)/html/*.html $(builddir)/html/*.png $(builddir)/html/*.css`; \ + if test "$$installfiles" = '$(builddir)/html/*.sgml $(builddir)/html/*.html $(builddir)/html/*.png $(builddir)/html/*.css'; \ + then echo '-- Nothing to install' ; \ + else \ + $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR); \ + for i in $$installfiles; do \ + echo '-- Installing '$$i ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \ + done; \ + echo '-- Installing $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2' ; \ + if test -e $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; then \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2 \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; \ + fi; \ + $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$(DESTDIR)$(TARGET_DIR) || true ; \ + fi) +uninstall-local: + if test -d $(DESTDIR)$(TARGET_DIR); then \ + rm -rf $(DESTDIR)$(TARGET_DIR)/*; \ + rmdir -p $(DESTDIR)$(TARGET_DIR) 2>/dev/null || true; \ + else \ + echo '-- Nothing to uninstall' ; \ + fi; + +# +# Require gtk-doc when making dist +# +@ENABLE_GTK_DOC_TRUE@dist-check-gtkdoc: +@ENABLE_GTK_DOC_FALSE@dist-check-gtkdoc: +@ENABLE_GTK_DOC_FALSE@ @echo "*** gtk-doc must be installed and enabled in order to make dist" +@ENABLE_GTK_DOC_FALSE@ @false + +dist-hook: dist-check-gtkdoc dist-hook-local + mkdir $(distdir)/html + cp html/* $(distdir)/html + -cp $(srcdir)/$(DOC_MODULE).types $(distdir)/ + -cp $(srcdir)/$(DOC_MODULE)-sections.txt $(distdir)/ + cd $(distdir) && rm -f $(DISTCLEANFILES) + -gtkdoc-rebase --online --relative --html-dir=$(distdir)/html + +.PHONY : dist-hook-local docs + +# avoid spurious build errors when distchecking with -jN +.NOTPARALLEL: + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/docs/libs/gst-rtsp-server-docs.sgml b/docs/libs/gst-rtsp-server-docs.sgml new file mode 100644 index 0000000..06141f8 --- /dev/null +++ b/docs/libs/gst-rtsp-server-docs.sgml @@ -0,0 +1,49 @@ + + +%version-entities; +]> + + + + GStreamer RTSP Server Reference Manual + + for GStreamer RTSP Server &GST_VERSION; + + + + + + + + + + + + + + + + + + + + + + + + + + + Object Hierarchy + + + + + API Index + + + + + diff --git a/docs/libs/gst-rtsp-server-overrides.txt b/docs/libs/gst-rtsp-server-overrides.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/libs/gst-rtsp-server-sections.txt b/docs/libs/gst-rtsp-server-sections.txt new file mode 100644 index 0000000..e832c4e --- /dev/null +++ b/docs/libs/gst-rtsp-server-sections.txt @@ -0,0 +1,697 @@ +
+rtsp-address-pool +GstRTSPAddressPool + + +GST_RTSP_ADDRESS_POOL_ANY_IPV4 +GST_RTSP_ADDRESS_POOL_ANY_IPV6 +GstRTSPAddress +GstRTSPAddressFlags +gst_rtsp_address_copy +gst_rtsp_address_free + + +GstRTSPAddressPool +GstRTSPAddressPoolClass +GstRTSPAddressPoolResult +gst_rtsp_address_pool_new +gst_rtsp_address_pool_clear +gst_rtsp_address_pool_dump +gst_rtsp_address_pool_add_range +gst_rtsp_address_pool_has_unicast_addresses +gst_rtsp_address_pool_acquire_address +gst_rtsp_address_pool_reserve_address + +GST_RTSP_ADDRESS_POOL_CAST +GST_RTSP_ADDRESS_POOL_CLASS_CAST +GST_IS_RTSP_ADDRESS_POOL +GST_IS_RTSP_ADDRESS_POOL_CLASS +GST_RTSP_ADDRESS_POOL +GST_RTSP_ADDRESS_POOL_CLASS +GST_RTSP_ADDRESS_POOL_GET_CLASS +GST_TYPE_RTSP_ADDRESS_POOL +GstRTSPAddressPoolPrivate +gst_rtsp_address_get_type +gst_rtsp_address_pool_get_type +
+ +
+rtsp-auth +GstRTSPAuth +GstRTSPAuth +GstRTSPAuthClass +gst_rtsp_auth_new + +gst_rtsp_auth_get_tls_certificate +gst_rtsp_auth_set_tls_certificate +gst_rtsp_auth_make_basic +gst_rtsp_auth_add_basic +gst_rtsp_auth_remove_basic +gst_rtsp_auth_check +gst_rtsp_auth_get_default_token +gst_rtsp_auth_set_default_token + + +GST_RTSP_AUTH_CHECK_CONNECT +GST_RTSP_AUTH_CHECK_URL +GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS +GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT +GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS + + +GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE +GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS + + +GST_RTSP_PERM_MEDIA_FACTORY_ACCESS +GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT + +GST_RTSP_AUTH_CAST +GST_RTSP_AUTH_CLASS_CAST +GST_IS_RTSP_AUTH +GST_IS_RTSP_AUTH_CLASS +GST_RTSP_AUTH +GST_RTSP_AUTH_CLASS +GST_RTSP_AUTH_GET_CLASS +GST_TYPE_RTSP_AUTH +GstRTSPAuthPrivate +gst_rtsp_auth_get_type +
+ +
+rtsp-client +GstRTSPClient + +GstRTSPClient +GstRTSPClientClass + +gst_rtsp_client_new +gst_rtsp_client_close + +gst_rtsp_client_get_session_pool +gst_rtsp_client_set_session_pool + +gst_rtsp_client_get_mount_points +gst_rtsp_client_set_mount_points + +gst_rtsp_client_get_auth +gst_rtsp_client_set_auth + +gst_rtsp_client_get_thread_pool +gst_rtsp_client_set_thread_pool + +gst_rtsp_client_get_connection +gst_rtsp_client_set_connection + +gst_rtsp_client_attach + +GstRTSPClientSendFunc +gst_rtsp_client_set_send_func + +gst_rtsp_client_handle_message +gst_rtsp_client_send_message + +GstRTSPClientSessionFilterFunc +gst_rtsp_client_session_filter + +GST_RTSP_CLIENT_CAST +GST_RTSP_CLIENT_CLASS_CAST +GST_IS_RTSP_CLIENT +GST_IS_RTSP_CLIENT_CLASS +GST_RTSP_CLIENT +GST_RTSP_CLIENT_CLASS +GST_RTSP_CLIENT_GET_CLASS +GST_TYPE_RTSP_CLIENT +GstRTSPClientPrivate +gst_rtsp_client_get_type +
+ +
+rtsp-context +GstRTSPContext +GstRTSPContext +gst_rtsp_context_get_current +gst_rtsp_context_push_current +gst_rtsp_context_pop_current + +GST_TYPE_RTSP_CONTEXT +gst_rtsp_context_get_type +
+ +
+rtsp-media +GstRTSPMedia +GstRTSPMedia +GstRTSPMediaClass +gst_rtsp_media_new +gst_rtsp_media_get_element +gst_rtsp_media_take_pipeline + +gst_rtsp_media_set_permissions +gst_rtsp_media_get_permissions + +gst_rtsp_media_set_shared +gst_rtsp_media_is_shared + +gst_rtsp_media_set_reusable +gst_rtsp_media_is_reusable + +gst_rtsp_media_set_profiles +gst_rtsp_media_get_profiles + +gst_rtsp_media_set_protocols +gst_rtsp_media_get_protocols + +gst_rtsp_media_set_eos_shutdown +gst_rtsp_media_is_eos_shutdown + +gst_rtsp_media_set_address_pool +gst_rtsp_media_get_address_pool + +gst_rtsp_media_set_buffer_size +gst_rtsp_media_get_buffer_size + +gst_rtsp_media_setup_sdp + + +gst_rtsp_media_prepare +gst_rtsp_media_unprepare +GstRTSPMediaStatus +gst_rtsp_media_get_status + + +gst_rtsp_media_set_suspend_mode +gst_rtsp_media_get_suspend_mode + +GstRTSPSuspendMode +gst_rtsp_media_suspend +gst_rtsp_media_unsuspend + + +gst_rtsp_media_collect_streams +gst_rtsp_media_create_stream +gst_rtsp_media_n_streams +gst_rtsp_media_get_stream +gst_rtsp_media_find_stream + + +gst_rtsp_media_seek +gst_rtsp_media_get_range_string + +gst_rtsp_media_set_state +gst_rtsp_media_set_pipeline_state + + +gst_rtsp_media_get_clock +gst_rtsp_media_get_base_time +gst_rtsp_media_use_time_provider +gst_rtsp_media_is_time_provider +gst_rtsp_media_get_time_provider + +GST_RTSP_MEDIA_CAST +GST_RTSP_MEDIA_CLASS_CAST +GST_IS_RTSP_MEDIA +GST_IS_RTSP_MEDIA_CLASS +GST_RTSP_MEDIA +GST_RTSP_MEDIA_CLASS +GST_RTSP_MEDIA_GET_CLASS +GST_TYPE_RTSP_MEDIA +GstRTSPMediaPrivate +gst_rtsp_media_get_type +GST_TYPE_RTSP_SUSPEND_MODE +gst_rtsp_suspend_mode_get_type +
+ +
+rtsp-media-factory +GstRTSPMediaFactory +GstRTSPMediaFactory +GstRTSPMediaFactoryClass +gst_rtsp_media_factory_new + +gst_rtsp_media_factory_get_launch +gst_rtsp_media_factory_set_launch + +gst_rtsp_media_factory_get_permissions +gst_rtsp_media_factory_set_permissions +gst_rtsp_media_factory_add_role + +gst_rtsp_media_factory_set_shared +gst_rtsp_media_factory_is_shared + +gst_rtsp_media_factory_is_eos_shutdown +gst_rtsp_media_factory_set_eos_shutdown + +gst_rtsp_media_factory_get_protocols +gst_rtsp_media_factory_set_protocols + +gst_rtsp_media_factory_set_profiles +gst_rtsp_media_factory_get_profiles + +gst_rtsp_media_factory_get_address_pool +gst_rtsp_media_factory_set_address_pool + +gst_rtsp_media_factory_get_buffer_size +gst_rtsp_media_factory_set_buffer_size + +gst_rtsp_media_factory_get_suspend_mode +gst_rtsp_media_factory_set_suspend_mode + +gst_rtsp_media_factory_construct +gst_rtsp_media_factory_create_element + + +GST_RTSP_MEDIA_FACTORY_CAST +GST_RTSP_MEDIA_FACTORY_CLASS_CAST +GST_IS_RTSP_MEDIA_FACTORY +GST_IS_RTSP_MEDIA_FACTORY_CLASS +GST_RTSP_MEDIA_FACTORY +GST_RTSP_MEDIA_FACTORY_CLASS +GST_RTSP_MEDIA_FACTORY_GET_CLASS +GST_TYPE_RTSP_MEDIA_FACTORY +GstRTSPMediaFactoryPrivate +gst_rtsp_media_factory_get_type +
+ +
+rtsp-media-factory-uri +GstRTSPMediaFactoryURI +GstRTSPMediaFactoryURI +GstRTSPMediaFactoryURIClass +gst_rtsp_media_factory_uri_new +gst_rtsp_media_factory_uri_set_uri +gst_rtsp_media_factory_uri_get_uri + +GST_RTSP_MEDIA_FACTORY_URI_CAST +GST_RTSP_MEDIA_FACTORY_URI_CLASS_CAST +GST_IS_RTSP_MEDIA_FACTORY_URI +GST_IS_RTSP_MEDIA_FACTORY_URI_CLASS +GST_RTSP_MEDIA_FACTORY_URI +GST_RTSP_MEDIA_FACTORY_URI_CLASS +GST_RTSP_MEDIA_FACTORY_URI_GET_CLASS +GST_TYPE_RTSP_MEDIA_FACTORY_URI +GstRTSPMediaFactoryURIPrivate +gst_rtsp_media_factory_uri_get_type +
+ +
+rtsp-mount-points +GstRTSPMountPoints +GstRTSPMountPoints +GstRTSPMountPointsClass +gst_rtsp_mount_points_new +gst_rtsp_mount_points_add_factory +gst_rtsp_mount_points_remove_factory +gst_rtsp_mount_points_match +gst_rtsp_mount_points_make_path + +GST_RTSP_MOUNT_POINTS_CAST +GST_RTSP_MOUNT_POINTS_CLASS_CAST +GST_IS_RTSP_MOUNT_POINTS +GST_IS_RTSP_MOUNT_POINTS_CLASS +GST_RTSP_MOUNT_POINTS +GST_RTSP_MOUNT_POINTS_CLASS +GST_RTSP_MOUNT_POINTS_GET_CLASS +GST_TYPE_RTSP_MOUNT_POINTS +GstRTSPMountPointsPrivate +gst_rtsp_mount_points_get_type +
+ +
+rtsp-params +GstRTSPParams +gst_rtsp_params_get +gst_rtsp_params_set +
+ +
+rtsp-permissions +GstRTSPPermissions +GstRTSPPermissions +gst_rtsp_permissions_new +gst_rtsp_permissions_ref +gst_rtsp_permissions_unref +gst_rtsp_permissions_add_role +gst_rtsp_permissions_add_role_valist +gst_rtsp_permissions_remove_role +gst_rtsp_permissions_get_role +gst_rtsp_permissions_is_allowed + +GST_RTSP_PERMISSIONS_CAST +GST_IS_RTSP_PERMISSIONS +GST_RTSP_PERMISSIONS +GST_TYPE_RTSP_PERMISSIONS +gst_rtsp_permissions_get_type +
+ +
+rtsp-sdp +GstRTSPSdp +GstSDPInfo +gst_rtsp_sdp_from_media +
+ +
+rtsp-server +GstRTSPServer +GstRTSPServer +GstRTSPServerClass + +gst_rtsp_server_new + +gst_rtsp_server_get_address +gst_rtsp_server_set_address + +gst_rtsp_server_get_service +gst_rtsp_server_set_service + +gst_rtsp_server_get_backlog +gst_rtsp_server_set_backlog + +gst_rtsp_server_get_bound_port + +gst_rtsp_server_get_mount_points +gst_rtsp_server_set_mount_points + +gst_rtsp_server_get_session_pool +gst_rtsp_server_set_session_pool + +gst_rtsp_server_get_thread_pool +gst_rtsp_server_set_thread_pool + +gst_rtsp_server_get_auth +gst_rtsp_server_set_auth + +gst_rtsp_server_transfer_connection +gst_rtsp_server_io_func +gst_rtsp_server_create_socket +gst_rtsp_server_create_source +gst_rtsp_server_attach + +GstRTSPServerClientFilterFunc +gst_rtsp_server_client_filter + + +GST_IS_RTSP_SERVER +GST_RTSP_SERVER_CAST +GST_RTSP_SERVER_CLASS_CAST +GST_IS_RTSP_SERVER_CLASS +GST_RTSP_SERVER +GST_RTSP_SERVER_CLASS +GST_RTSP_SERVER_GET_CLASS +GST_TYPE_RTSP_SERVER +GstRTSPServerPrivate +gst_rtsp_server_get_type +
+ +
+rtsp-session +GstRTSPSession +GstRTSPSession +GstRTSPSessionClass + +gst_rtsp_session_new +gst_rtsp_session_get_sessionid + +gst_rtsp_session_get_header + +gst_rtsp_session_set_timeout +gst_rtsp_session_get_timeout + +gst_rtsp_session_touch +gst_rtsp_session_prevent_expire +gst_rtsp_session_allow_expire +gst_rtsp_session_next_timeout +gst_rtsp_session_is_expired + +gst_rtsp_session_manage_media +gst_rtsp_session_release_media + +gst_rtsp_session_get_media + +GstRTSPFilterResult +GstRTSPSessionFilterFunc +gst_rtsp_session_filter + +GST_RTSP_SESSION_CAST +GST_RTSP_SESSION_CLASS_CAST +GST_IS_RTSP_SESSION +GST_IS_RTSP_SESSION_CLASS +GST_RTSP_SESSION +GST_RTSP_SESSION_CLASS +GST_RTSP_SESSION_GET_CLASS +GST_TYPE_RTSP_SESSION +GstRTSPSessionPrivate +gst_rtsp_session_get_type +
+ +
+rtsp-session-media +GstRTSPSessionMedia +GstRTSPSessionMedia +GstRTSPSessionMediaClass +gst_rtsp_session_media_new +gst_rtsp_session_media_matches + +gst_rtsp_session_media_get_media +gst_rtsp_session_media_get_base_time +gst_rtsp_session_media_get_rtpinfo + +gst_rtsp_session_media_set_state + +gst_rtsp_session_media_get_rtsp_state +gst_rtsp_session_media_set_rtsp_state + +gst_rtsp_session_media_get_transport +gst_rtsp_session_media_set_transport + +gst_rtsp_session_media_alloc_channels + +GST_RTSP_SESSION_MEDIA_CAST +GST_RTSP_SESSION_MEDIA_CLASS_CAST +GST_IS_RTSP_SESSION_MEDIA +GST_IS_RTSP_SESSION_MEDIA_CLASS +GST_RTSP_SESSION_MEDIA +GST_RTSP_SESSION_MEDIA_CLASS +GST_RTSP_SESSION_MEDIA_GET_CLASS +GST_TYPE_RTSP_SESSION_MEDIA +GstRTSPSessionMediaPrivate +gst_rtsp_session_media_get_type +
+ +
+rtsp-session-pool +GstRTSPSessionPool +GstRTSPSessionPool +GstRTSPSessionPoolClass +gst_rtsp_session_pool_new + +gst_rtsp_session_pool_get_max_sessions +gst_rtsp_session_pool_set_max_sessions + +gst_rtsp_session_pool_get_n_sessions + +gst_rtsp_session_pool_create +gst_rtsp_session_pool_find +gst_rtsp_session_pool_remove + +gst_rtsp_session_pool_cleanup + +GstRTSPSessionPoolFunc +gst_rtsp_session_pool_create_watch + +GstRTSPSessionPoolFilterFunc +gst_rtsp_session_pool_filter + +GST_RTSP_SESSION_POOL_CAST +GST_RTSP_SESSION_POOL_CLASS_CAST +GST_IS_RTSP_SESSION_POOL +GST_IS_RTSP_SESSION_POOL_CLASS +GST_RTSP_SESSION_POOL +GST_RTSP_SESSION_POOL_CLASS +GST_RTSP_SESSION_POOL_GET_CLASS +GST_TYPE_RTSP_SESSION_POOL +GstRTSPSessionPoolPrivate +gst_rtsp_session_pool_get_type +
+ +
+rtsp-stream +GstRTSPStream +GstRTSPStream +GstRTSPStreamClass +gst_rtsp_stream_new + +gst_rtsp_stream_get_index +gst_rtsp_stream_get_srcpad + +gst_rtsp_stream_get_control +gst_rtsp_stream_set_control +gst_rtsp_stream_has_control + +gst_rtsp_stream_get_mtu +gst_rtsp_stream_set_mtu + +gst_rtsp_stream_get_dscp_qos +gst_rtsp_stream_set_dscp_qos + +gst_rtsp_stream_set_profiles +gst_rtsp_stream_get_profiles + +gst_rtsp_stream_get_protocols +gst_rtsp_stream_set_protocols + +gst_rtsp_stream_is_transport_supported + +gst_rtsp_stream_get_address_pool +gst_rtsp_stream_set_address_pool +gst_rtsp_stream_reserve_address + +gst_rtsp_stream_join_bin +gst_rtsp_stream_leave_bin + +gst_rtsp_stream_get_server_port +gst_rtsp_stream_get_multicast_address +gst_rtsp_stream_get_rtpsession +gst_rtsp_stream_get_ssrc +gst_rtsp_stream_get_rtpinfo +gst_rtsp_stream_get_caps +gst_rtsp_stream_get_pt + +gst_rtsp_stream_recv_rtcp +gst_rtsp_stream_recv_rtp + +gst_rtsp_stream_add_transport +gst_rtsp_stream_remove_transport + +gst_rtsp_stream_get_rtp_socket +gst_rtsp_stream_get_rtcp_socket + +gst_rtsp_stream_set_blocked +gst_rtsp_stream_is_blocking + +gst_rtsp_stream_update_crypto + +GstRTSPStreamTransportFilterFunc +gst_rtsp_stream_transport_filter + + +GST_RTSP_STREAM_CAST +GST_RTSP_STREAM_CLASS_CAST +GST_IS_RTSP_STREAM +GST_IS_RTSP_STREAM_CLASS +GST_RTSP_STREAM +GST_RTSP_STREAM_CLASS +GST_RTSP_STREAM_GET_CLASS +GST_TYPE_RTSP_STREAM +GstRTSPStreamPrivate +gst_rtsp_stream_get_type +
+ +
+rtsp-stream-transport +GstRTSPStreamTransport +GstRTSPStreamTransport +GstRTSPStreamTransportClass +gst_rtsp_stream_transport_new + +gst_rtsp_stream_transport_get_stream + +gst_rtsp_stream_transport_get_transport +gst_rtsp_stream_transport_set_transport + +gst_rtsp_stream_transport_get_url +gst_rtsp_stream_transport_set_url + +gst_rtsp_stream_transport_get_rtpinfo + +GstRTSPSendFunc +gst_rtsp_stream_transport_set_callbacks + +GstRTSPKeepAliveFunc +gst_rtsp_stream_transport_set_keepalive +gst_rtsp_stream_transport_keep_alive + +gst_rtsp_stream_transport_set_active + +gst_rtsp_stream_transport_set_timed_out +gst_rtsp_stream_transport_is_timed_out + +gst_rtsp_stream_transport_send_rtcp +gst_rtsp_stream_transport_send_rtp + + +GST_RTSP_STREAM_TRANSPORT_CAST +GST_RTSP_STREAM_TRANSPORT_CLASS_CAST +GST_IS_RTSP_STREAM_TRANSPORT +GST_IS_RTSP_STREAM_TRANSPORT_CLASS +GST_RTSP_STREAM_TRANSPORT +GST_RTSP_STREAM_TRANSPORT_CLASS +GST_RTSP_STREAM_TRANSPORT_GET_CLASS +GST_TYPE_RTSP_STREAM_TRANSPORT +GstRTSPStreamTransportPrivate +gst_rtsp_stream_transport_get_type +
+ +
+rtsp-thread-pool +GstRTSPThreadPool + +GstRTSPThreadType +GstRTSPThread + +gst_rtsp_thread_new +gst_rtsp_thread_ref +gst_rtsp_thread_unref +gst_rtsp_thread_reuse +gst_rtsp_thread_stop + + +GstRTSPThreadPool +GstRTSPThreadPoolClass +gst_rtsp_thread_pool_new + +gst_rtsp_thread_pool_get_max_threads +gst_rtsp_thread_pool_set_max_threads + +gst_rtsp_thread_pool_get_thread +gst_rtsp_thread_pool_cleanup + +GST_RTSP_THREAD_CAST +GST_RTSP_THREAD_POOL_CAST +GST_RTSP_THREAD_POOL_CLASS_CAST +GST_IS_RTSP_THREAD +GST_IS_RTSP_THREAD_POOL +GST_IS_RTSP_THREAD_POOL_CLASS +GST_RTSP_THREAD +GST_RTSP_THREAD_POOL +GST_RTSP_THREAD_POOL_CLASS +GST_RTSP_THREAD_POOL_GET_CLASS +GST_TYPE_RTSP_THREAD +GST_TYPE_RTSP_THREAD_POOL +GstRTSPThreadPoolPrivate +gst_rtsp_thread_get_type +gst_rtsp_thread_pool_get_type +
+ +
+rtsp-token +GstRTSPToken +GstRTSPToken +gst_rtsp_token_new_empty +gst_rtsp_token_new +gst_rtsp_token_new_valist +gst_rtsp_token_ref +gst_rtsp_token_unref +gst_rtsp_token_get_structure +gst_rtsp_token_writable_structure +gst_rtsp_token_get_string +gst_rtsp_token_is_allowed + +GST_RTSP_TOKEN_CAST +GST_IS_RTSP_TOKEN +GST_RTSP_TOKEN +GST_TYPE_RTSP_TOKEN +gst_rtsp_token_get_type +
+ diff --git a/docs/libs/gst-rtsp-server.types b/docs/libs/gst-rtsp-server.types new file mode 100644 index 0000000..f4476f2 --- /dev/null +++ b/docs/libs/gst-rtsp-server.types @@ -0,0 +1,25 @@ +#include + +#include +gst_rtsp_auth_get_type + +#include +gst_rtsp_mount_points_get_type + +#include +gst_rtsp_media_factory_get_type + +#include +gst_rtsp_media_get_type + +#include +gst_rtsp_server_get_type + +#include +gst_rtsp_session_pool_get_type + +#include +gst_rtsp_session_get_type + +#include +gst_rtsp_client_get_type diff --git a/docs/libs/html/GstRTSPAuth.html b/docs/libs/html/GstRTSPAuth.html new file mode 100644 index 0000000..b51425a --- /dev/null +++ b/docs/libs/html/GstRTSPAuth.html @@ -0,0 +1,613 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPAuth + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPAuth

+

GstRTSPAuth — Authentication and authorization

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPAuth * + +gst_rtsp_auth_new () +
+GTlsCertificate * + +gst_rtsp_auth_get_tls_certificate () +
+void + +gst_rtsp_auth_set_tls_certificate () +
+gchar * + +gst_rtsp_auth_make_basic () +
+void + +gst_rtsp_auth_add_basic () +
+void + +gst_rtsp_auth_remove_basic () +
+gboolean + +gst_rtsp_auth_check () +
+GstRTSPToken * + +gst_rtsp_auth_get_default_token () +
+void + +gst_rtsp_auth_set_default_token () +
+
+ +
+

Object Hierarchy

+
    GObject
+    ╰── GstRTSPAuth
+
+
+
+

Description

+

The GstRTSPAuth object is responsible for checking if the current user is +allowed to perform requested actions. The default implementation has some +reasonable checks but subclasses can implement custom security policies.

+

A new auth object is made with gst_rtsp_auth_new(). It is usually configured +on the GstRTSPServer object.

+

The RTSP server will call gst_rtsp_auth_check() with a string describing the +check to perform. The possible checks are prefixed with +GST_RTSP_AUTH_CHECK_*. Depending on the check, the default implementation +will use the current GstRTSPToken, GstRTSPContext and +GstRTSPPermissions on the object to check if an operation is allowed.

+

The default GstRTSPAuth object has support for basic authentication. With +gst_rtsp_auth_add_basic() you can add a basic authentication string together +with the GstRTSPToken that will become active when successfully +authenticated.

+

When a TLS certificate has been set with gst_rtsp_auth_set_tls_certificate(), +the default auth object will require the client to connect with a TLS +connection.

+

Last reviewed on 2013-07-16 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_auth_new ()

+
GstRTSPAuth *
+gst_rtsp_auth_new (void);
+

Create a new GstRTSPAuth instance.

+
+

Returns

+

a new GstRTSPAuth.

+

[transfer full]

+
+
+
+
+

gst_rtsp_auth_get_tls_certificate ()

+
GTlsCertificate *
+gst_rtsp_auth_get_tls_certificate (GstRTSPAuth *auth);
+

Get the GTlsCertificate used for negotiating TLS auth +.

+
+

Parameters

+
+++++ + + + + + +

auth

a GstRTSPAuth

 
+
+
+

Returns

+

the GTlsCertificate of auth +. g_object_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_auth_set_tls_certificate ()

+
void
+gst_rtsp_auth_set_tls_certificate (GstRTSPAuth *auth,
+                                   GTlsCertificate *cert);
+

Set the TLS certificate for the auth. Client connections will only +be accepted when TLS is negotiated.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

auth

a GstRTSPAuth

 

cert

a GTlsCertificate.

[transfer none][allow-none]
+
+
+
+
+

gst_rtsp_auth_make_basic ()

+
gchar *
+gst_rtsp_auth_make_basic (const gchar *user,
+                          const gchar *pass);
+

Construct a Basic authorisation token from user + and pass +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

user

a userid

 

pass

a password

 
+
+
+

Returns

+

the base64 encoding of the string user +:pass +. +g_free() after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_auth_add_basic ()

+
void
+gst_rtsp_auth_add_basic (GstRTSPAuth *auth,
+                         const gchar *basic,
+                         GstRTSPToken *token);
+

Add a basic token for the default authentication algorithm that +enables the client with privileges listed in token +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

auth

a GstRTSPAuth

 

basic

the basic token

 

token

authorisation token.

[transfer none]
+
+
+
+
+

gst_rtsp_auth_remove_basic ()

+
void
+gst_rtsp_auth_remove_basic (GstRTSPAuth *auth,
+                            const gchar *basic);
+

Add a basic token for the default authentication algorithm that +enables the client with privileges from authgroup +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

auth

a GstRTSPAuth

 

basic

the basic token.

[transfer none]
+
+
+
+
+

gst_rtsp_auth_check ()

+
gboolean
+gst_rtsp_auth_check (const gchar *check);
+

Check if check + is allowed in the current context.

+
+

Parameters

+
+++++ + + + + + +

check

the item to check

 
+
+
+

Returns

+

FALSE if check failed.

+

+
+
+
+
+

gst_rtsp_auth_get_default_token ()

+
GstRTSPToken *
+gst_rtsp_auth_get_default_token (GstRTSPAuth *auth);
+

Get the default token for auth +. This token will be used for unauthenticated +users.

+
+

Parameters

+
+++++ + + + + + +

auth

a GstRTSPAuth

 
+
+
+

Returns

+

the GstRTSPToken of auth +. gst_rtsp_token_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_auth_set_default_token ()

+
void
+gst_rtsp_auth_set_default_token (GstRTSPAuth *auth,
+                                 GstRTSPToken *token);
+

Set the default GstRTSPToken to token + in auth +. The default token will +be used for unauthenticated users.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

auth

a GstRTSPAuth

 

token

a GstRTSPToken.

[transfer none][allow-none]
+
+
+
+
+

Types and Values

+
+

struct GstRTSPAuth

+
struct GstRTSPAuth;
+

The authentication structure.

+
+
+
+

struct GstRTSPAuthClass

+
struct GstRTSPAuthClass {
+  GObjectClass  parent_class;
+
+  gboolean           (*authenticate) (GstRTSPAuth *auth, GstRTSPContext *ctx);
+  gboolean           (*check)        (GstRTSPAuth *auth, GstRTSPContext *ctx,
+                                      const gchar *check);
+};
+
+

The authentication class.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GObjectClass parent_class;

  

authenticate ()

check the authentication of a client. The default implementation +checks if the authentication in the header matches one of the basic +authentication tokens. This function should set the authgroup field +in the context.

 

check ()

check if a resource can be accessed. this function should +call authenticate to authenticate the client when needed. The method +should also construct and send an appropriate response message on +error.

 
+
+
+
+
+

GST_RTSP_AUTH_CHECK_CONNECT

+
#define GST_RTSP_AUTH_CHECK_CONNECT                  "auth.check.connect"
+
+

Check a new connection

+
+
+
+

GST_RTSP_AUTH_CHECK_URL

+
#define GST_RTSP_AUTH_CHECK_URL                      "auth.check.url"
+
+

Check the URL and methods

+
+
+
+

GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS

+
#define GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS     "auth.check.media.factory.access"
+
+

Check if access is allowed to a factory. +When access is not allowed an 404 Not Found is sent in the response.

+
+
+
+

GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT

+
#define GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT  "auth.check.media.factory.construct"
+
+

Check if media can be constructed from a media factory +A response should be sent on error.

+
+
+
+

GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS

+
#define GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS  "auth.check.transport.client-settings"
+
+

Check if the client can specify TTL, destination and +port pair in multicast. No response is sent when the check returns +FALSE.

+
+
+
+

GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE

+
#define GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE      "media.factory.role"
+
+

G_TYPE_STRING, the role to use when dealing with media factories

+

The default GstRTSPAuth object uses this string in the token to find the +role of the media factory. It will then retrieve the GstRTSPPermissions of +the media factory and retrieve the role with the same name.

+
+
+
+

GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS

+
#define GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS   "transport.client-settings"
+
+

G_TYPE_BOOLEAN, TRUE if the client can specify TTL, destination and + port pair in multicast.

+
+
+
+

GST_RTSP_PERM_MEDIA_FACTORY_ACCESS

+
#define GST_RTSP_PERM_MEDIA_FACTORY_ACCESS      "media.factory.access"
+
+

G_TYPE_BOOLEAN, TRUE if the media can be accessed, FALSE will +return a 404 Not Found error when trying to access the media.

+
+
+
+

GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT

+
#define GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT   "media.factory.construct"
+
+

G_TYPE_BOOLEAN, TRUE if the media can be constructed, FALSE will +return a 404 Not Found error when trying to access the media.

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstRTSPClient.html b/docs/libs/html/GstRTSPClient.html new file mode 100644 index 0000000..d806b44 --- /dev/null +++ b/docs/libs/html/GstRTSPClient.html @@ -0,0 +1,1371 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPClient + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPClient

+

GstRTSPClient — A client connection state

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPClient * + +gst_rtsp_client_new () +
+void + +gst_rtsp_client_close () +
+GstRTSPSessionPool * + +gst_rtsp_client_get_session_pool () +
+void + +gst_rtsp_client_set_session_pool () +
+GstRTSPMountPoints * + +gst_rtsp_client_get_mount_points () +
+void + +gst_rtsp_client_set_mount_points () +
+GstRTSPAuth * + +gst_rtsp_client_get_auth () +
+void + +gst_rtsp_client_set_auth () +
+GstRTSPThreadPool * + +gst_rtsp_client_get_thread_pool () +
+void + +gst_rtsp_client_set_thread_pool () +
+GstRTSPConnection * + +gst_rtsp_client_get_connection () +
+gboolean + +gst_rtsp_client_set_connection () +
+guint + +gst_rtsp_client_attach () +
+gboolean + +(*GstRTSPClientSendFunc) () +
+void + +gst_rtsp_client_set_send_func () +
+GstRTSPResult + +gst_rtsp_client_handle_message () +
+GstRTSPResult + +gst_rtsp_client_send_message () +
+GstRTSPFilterResult + +(*GstRTSPClientSessionFilterFunc) () +
+GList * + +gst_rtsp_client_session_filter () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + +
gbooleandrop-backlogRead / Write
+GstRTSPMountPoints *mount-pointsRead / Write
+GstRTSPSessionPool *session-poolRead / Write
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
voidclosedRun Last
voiddescribe-requestRun Last
voidget-parameter-requestRun Last
voidhandle-responseRun Last
voidnew-sessionRun Last
voidoptions-requestRun Last
voidpause-requestRun Last
voidplay-requestRun Last
voidsend-messageRun Last
voidset-parameter-requestRun Last
voidsetup-requestRun Last
voidteardown-requestRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstRTSPClient
structGstRTSPClientClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GstRTSPClient
+
+
+
+

Description

+

The client object handles the connection with a client for as long as a TCP +connection is open.

+

A GstRTSPClient is created by GstRTSPServer when a new connection is +accepted and it inherits the GstRTSPMountPoints, GstRTSPSessionPool, +GstRTSPAuth and GstRTSPThreadPool from the server.

+

The client connection should be configured with the GstRTSPConnection using +gst_rtsp_client_set_connection() before it can be attached to a GMainContext +using gst_rtsp_client_attach(). From then on the client will handle requests +on the connection.

+

Use gst_rtsp_client_session_filter() to iterate or modify all the +GstRTSPSession objects managed by the client object.

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_client_new ()

+
GstRTSPClient *
+gst_rtsp_client_new (void);
+

Create a new GstRTSPClient instance.

+
+

Returns

+

a new GstRTSPClient.

+

[transfer full]

+
+
+
+
+

gst_rtsp_client_close ()

+
void
+gst_rtsp_client_close (GstRTSPClient *client);
+

Close the connection of client + and remove all media it was managing.

+
+

Parameters

+
+++++ + + + + + +

client

a GstRTSPClient

 
+
+

Since 1.4

+
+
+
+

gst_rtsp_client_get_session_pool ()

+
GstRTSPSessionPool *
+gst_rtsp_client_get_session_pool (GstRTSPClient *client);
+

Get the GstRTSPSessionPool object that client + uses to manage its sessions.

+
+

Parameters

+
+++++ + + + + + +

client

a GstRTSPClient

 
+
+
+

Returns

+

a GstRTSPSessionPool, unref after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_client_set_session_pool ()

+
void
+gst_rtsp_client_set_session_pool (GstRTSPClient *client,
+                                  GstRTSPSessionPool *pool);
+

Set pool + as the sessionpool for client + which it will use to find +or allocate sessions. the sessionpool is usually inherited from the server +that created the client but can be overridden later.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

client

a GstRTSPClient

 

pool

a GstRTSPSessionPool.

[transfer none]
+
+
+
+
+

gst_rtsp_client_get_mount_points ()

+
GstRTSPMountPoints *
+gst_rtsp_client_get_mount_points (GstRTSPClient *client);
+

Get the GstRTSPMountPoints object that client + uses to manage its sessions.

+
+

Parameters

+
+++++ + + + + + +

client

a GstRTSPClient

 
+
+
+

Returns

+

a GstRTSPMountPoints, unref after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_client_set_mount_points ()

+
void
+gst_rtsp_client_set_mount_points (GstRTSPClient *client,
+                                  GstRTSPMountPoints *mounts);
+

Set mounts + as the mount points for client + which it will use to map urls +to media streams. These mount points are usually inherited from the server that +created the client but can be overriden later.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

client

a GstRTSPClient

 

mounts

a GstRTSPMountPoints.

[transfer none]
+
+
+
+
+

gst_rtsp_client_get_auth ()

+
GstRTSPAuth *
+gst_rtsp_client_get_auth (GstRTSPClient *client);
+

Get the GstRTSPAuth used as the authentication manager of client +.

+
+

Parameters

+
+++++ + + + + + +

client

a GstRTSPClient

 
+
+
+

Returns

+

the GstRTSPAuth of client +. g_object_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_client_set_auth ()

+
void
+gst_rtsp_client_set_auth (GstRTSPClient *client,
+                          GstRTSPAuth *auth);
+

configure auth + to be used as the authentication manager of client +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

client

a GstRTSPClient

 

auth

a GstRTSPAuth.

[transfer none]
+
+
+
+
+

gst_rtsp_client_get_thread_pool ()

+
GstRTSPThreadPool *
+gst_rtsp_client_get_thread_pool (GstRTSPClient *client);
+

Get the GstRTSPThreadPool used as the thread pool of client +.

+
+

Parameters

+
+++++ + + + + + +

client

a GstRTSPClient

 
+
+
+

Returns

+

the GstRTSPThreadPool of client +. g_object_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_client_set_thread_pool ()

+
void
+gst_rtsp_client_set_thread_pool (GstRTSPClient *client,
+                                 GstRTSPThreadPool *pool);
+

configure pool + to be used as the thread pool of client +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

client

a GstRTSPClient

 

pool

a GstRTSPThreadPool.

[transfer none]
+
+
+
+
+

gst_rtsp_client_get_connection ()

+
GstRTSPConnection *
+gst_rtsp_client_get_connection (GstRTSPClient *client);
+

Get the GstRTSPConnection of client +.

+
+

Parameters

+
+++++ + + + + + +

client

a GstRTSPClient

 
+
+
+

Returns

+

the GstRTSPConnection of client +. +The connection object returned remains valid until the client is freed.

+

[transfer none]

+
+
+
+
+

gst_rtsp_client_set_connection ()

+
gboolean
+gst_rtsp_client_set_connection (GstRTSPClient *client,
+                                GstRTSPConnection *conn);
+

Set the GstRTSPConnection of client +. This function takes ownership of +conn +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

client

a GstRTSPClient

 

conn

a GstRTSPConnection.

[transfer full]
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

gst_rtsp_client_attach ()

+
guint
+gst_rtsp_client_attach (GstRTSPClient *client,
+                        GMainContext *context);
+

Attaches client + to context +. When the mainloop for context + is run, the +client will be dispatched. When context + is NULL, the default context will be +used).

+

This function should be called when the client properties and urls are fully +configured and the client is ready to start.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

client

a GstRTSPClient

 

context

a GMainContext.

[allow-none]
+
+
+

Returns

+

the ID (greater than 0) for the source within the GMainContext.

+

+
+
+
+
+

GstRTSPClientSendFunc ()

+
gboolean
+(*GstRTSPClientSendFunc) (GstRTSPClient *client,
+                          GstRTSPMessage *message,
+                          gboolean close,
+                          gpointer user_data);
+

This callback is called when client + wants to send message +. When close + is +TRUE, the connection should be closed when the message has been sent.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

client

a GstRTSPClient

 

message

a GstRTSPMessage

 

close

close the connection

 

user_data

user data when registering the callback

 
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

gst_rtsp_client_set_send_func ()

+
void
+gst_rtsp_client_set_send_func (GstRTSPClient *client,
+                               GstRTSPClientSendFunc func,
+                               gpointer user_data,
+                               GDestroyNotify notify);
+

Set func + as the callback that will be called when a new message needs to be +sent to the client. user_data + is passed to func + and notify + is called when +user_data + is no longer in use.

+

By default, the client will send the messages on the GstRTSPConnection that +was configured with gst_rtsp_client_attach() was called.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

client

a GstRTSPClient

 

func

a GstRTSPClientSendFunc.

[scope notified]

user_data

user data passed to func +.

[closure]

notify

called when user_data +is no longer in use.

[allow-none]
+
+
+
+
+

gst_rtsp_client_handle_message ()

+
GstRTSPResult
+gst_rtsp_client_handle_message (GstRTSPClient *client,
+                                GstRTSPMessage *message);
+

Let the client handle message +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

client

a GstRTSPClient

 

message

an GstRTSPMessage.

[transfer none]
+
+
+

Returns

+

a GstRTSPResult.

+

+
+
+
+
+

gst_rtsp_client_send_message ()

+
GstRTSPResult
+gst_rtsp_client_send_message (GstRTSPClient *client,
+                              GstRTSPSession *session,
+                              GstRTSPMessage *message);
+

Send a message message to the remote end. message + must be a +GST_RTSP_MESSAGE_REQUEST or a GST_RTSP_MESSAGE_RESPONSE.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

client

a GstRTSPClient

 

session

a GstRTSPSession to send +the message to or NULL.

[allow-none][transfer none]

message

The GstRTSPMessage to send.

[transfer none]
+
+
+
+
+

GstRTSPClientSessionFilterFunc ()

+
GstRTSPFilterResult
+(*GstRTSPClientSessionFilterFunc) (GstRTSPClient *client,
+                                   GstRTSPSession *sess,
+                                   gpointer user_data);
+

This function will be called by the gst_rtsp_client_session_filter(). An +implementation should return a value of GstRTSPFilterResult.

+

When this function returns GST_RTSP_FILTER_REMOVE, sess + will be removed +from client +.

+

A return value of GST_RTSP_FILTER_KEEP will leave sess + untouched in +client +.

+

A value of GST_RTSP_FILTER_REF will add sess + to the result GList of +gst_rtsp_client_session_filter().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

client

a GstRTSPClient object

 

sess

a GstRTSPSession in client +

 

user_data

user data that has been given to gst_rtsp_client_session_filter()

 
+
+
+

Returns

+

a GstRTSPFilterResult.

+

+
+
+
+
+

gst_rtsp_client_session_filter ()

+
GList *
+gst_rtsp_client_session_filter (GstRTSPClient *client,
+                                GstRTSPClientSessionFilterFunc func,
+                                gpointer user_data);
+

Call func + for each session managed by client +. The result value of func + +determines what happens to the session. func + will be called with client + +locked so no further actions on client + can be performed from func +.

+

If func + returns GST_RTSP_FILTER_REMOVE, the session will be removed from +client +.

+

If func + returns GST_RTSP_FILTER_KEEP, the session will remain in client +.

+

If func + returns GST_RTSP_FILTER_REF, the session will remain in client + but +will also be added with an additional ref to the result GList of this +function..

+

When func + is NULL, GST_RTSP_FILTER_REF will be assumed for each session.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

client

a GstRTSPClient

 

func

a callback.

[scope call][allow-none]

user_data

user data passed to func +

 
+
+
+

Returns

+

a GList with all +sessions for which func +returned GST_RTSP_FILTER_REF. After usage, each +element in the GList should be unreffed before the list is freed.

+

[element-type GstRTSPSession][transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstRTSPClient

+
struct GstRTSPClient;
+

The client object represents the connection and its state with a client.

+
+
+
+

struct GstRTSPClientClass

+
struct GstRTSPClientClass {
+  GObjectClass  parent_class;
+
+  GstSDPMessage * (*create_sdp) (GstRTSPClient *client, GstRTSPMedia *media);
+  gboolean        (*configure_client_media)     (GstRTSPClient * client,
+                                                 GstRTSPMedia * media, GstRTSPStream * stream,
+                                                 GstRTSPContext * ctx);
+  gboolean        (*configure_client_transport) (GstRTSPClient * client,
+                                                 GstRTSPContext * ctx,
+                                                 GstRTSPTransport * ct);
+  GstRTSPResult   (*params_set) (GstRTSPClient *client, GstRTSPContext *ctx);
+  GstRTSPResult   (*params_get) (GstRTSPClient *client, GstRTSPContext *ctx);
+  gchar *         (*make_path_from_uri) (GstRTSPClient *client, const GstRTSPUrl *uri);
+
+  /* signals */
+  void     (*closed)                  (GstRTSPClient *client);
+  void     (*new_session)             (GstRTSPClient *client, GstRTSPSession *session);
+  void     (*options_request)         (GstRTSPClient *client, GstRTSPContext *ctx);
+  void     (*describe_request)        (GstRTSPClient *client, GstRTSPContext *ctx);
+  void     (*setup_request)           (GstRTSPClient *client, GstRTSPContext *ctx);
+  void     (*play_request)            (GstRTSPClient *client, GstRTSPContext *ctx);
+  void     (*pause_request)           (GstRTSPClient *client, GstRTSPContext *ctx);
+  void     (*teardown_request)        (GstRTSPClient *client, GstRTSPContext *ctx);
+  void     (*set_parameter_request)   (GstRTSPClient *client, GstRTSPContext *ctx);
+  void     (*get_parameter_request)   (GstRTSPClient *client, GstRTSPContext *ctx);
+  void     (*handle_response)         (GstRTSPClient *client, GstRTSPContext *ctx);
+
+  void     (*tunnel_http_response)    (GstRTSPClient * client, GstRTSPMessage * request,
+                                       GstRTSPMessage * response);
+};
+
+

The client class structure.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GObjectClass parent_class;

  

create_sdp ()

called when the SDP needs to be created for media.

 

configure_client_media ()

called when the stream in media needs to be configured. +The default implementation will configure the blocksize on the payloader when +spcified in the request headers.

 

configure_client_transport ()

called when the client transport needs to be +configured.

 

params_set ()

set parameters. This function should also initialize the +RTSP response(ctx->response) via a call to gst_rtsp_message_init_response()

 

params_get ()

get parameters. This function should also initialize the +RTSP response(ctx->response) via a call to gst_rtsp_message_init_response()

 

make_path_from_uri ()

  

closed ()

  

new_session ()

  

options_request ()

  

describe_request ()

  

setup_request ()

  

play_request ()

  

pause_request ()

  

teardown_request ()

  

set_parameter_request ()

  

get_parameter_request ()

  

handle_response ()

  

tunnel_http_response ()

called when a response to the GET request is about to +be sent for a tunneled connection. The response can be modified. Since 1.4

 
+
+
+
+
+

Property Details

+
+

The “drop-backlog” property

+
  “drop-backlog”             gboolean
+

Drop data when the backlog queue is full.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “mount-points” property

+
  “mount-points”             GstRTSPMountPoints *
+

The mount points to use for client session.

+

Flags: Read / Write

+
+
+
+

The “session-pool” property

+
  “session-pool”             GstRTSPSessionPool *
+

The session pool to use for client session.

+

Flags: Read / Write

+
+
+
+

Signal Details

+
+

The “closed” signal

+
void
+user_function (GstRTSPClient *gstrtspclient,
+               gpointer       user_data)
+

Flags: Run Last

+
+
+
+

The “describe-request” signal

+
void
+user_function (GstRTSPClient  *gstrtspclient,
+               GstRTSPContext *arg1,
+               gpointer        user_data)
+

Flags: Run Last

+
+
+
+

The “get-parameter-request” signal

+
void
+user_function (GstRTSPClient  *gstrtspclient,
+               GstRTSPContext *arg1,
+               gpointer        user_data)
+

Flags: Run Last

+
+
+
+

The “handle-response” signal

+
void
+user_function (GstRTSPClient  *gstrtspclient,
+               GstRTSPContext *arg1,
+               gpointer        user_data)
+

Flags: Run Last

+
+
+
+

The “new-session” signal

+
void
+user_function (GstRTSPClient  *gstrtspclient,
+               GstRTSPSession *arg1,
+               gpointer        user_data)
+

Flags: Run Last

+
+
+
+

The “options-request” signal

+
void
+user_function (GstRTSPClient  *gstrtspclient,
+               GstRTSPContext *arg1,
+               gpointer        user_data)
+

Flags: Run Last

+
+
+
+

The “pause-request” signal

+
void
+user_function (GstRTSPClient  *gstrtspclient,
+               GstRTSPContext *arg1,
+               gpointer        user_data)
+

Flags: Run Last

+
+
+
+

The “play-request” signal

+
void
+user_function (GstRTSPClient  *gstrtspclient,
+               GstRTSPContext *arg1,
+               gpointer        user_data)
+

Flags: Run Last

+
+
+
+

The “send-message” signal

+
void
+user_function (GstRTSPClient  *client,
+               GstRTSPContext *session,
+               gpointer        message,
+               gpointer        user_data)
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

client

The RTSP client

 

session

The session.

[type GstRtspServer.RTSPSession]

message

The message.

[type GstRtsp.RTSPMessage]

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “set-parameter-request” signal

+
void
+user_function (GstRTSPClient  *gstrtspclient,
+               GstRTSPContext *arg1,
+               gpointer        user_data)
+

Flags: Run Last

+
+
+
+

The “setup-request” signal

+
void
+user_function (GstRTSPClient  *gstrtspclient,
+               GstRTSPContext *arg1,
+               gpointer        user_data)
+

Flags: Run Last

+
+
+
+

The “teardown-request” signal

+
void
+user_function (GstRTSPClient  *gstrtspclient,
+               GstRTSPContext *arg1,
+               gpointer        user_data)
+

Flags: Run Last

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstRTSPMedia.html b/docs/libs/html/GstRTSPMedia.html new file mode 100644 index 0000000..7005873 --- /dev/null +++ b/docs/libs/html/GstRTSPMedia.html @@ -0,0 +1,2286 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPMedia + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPMedia

+

GstRTSPMedia — The media pipeline

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPMedia * + +gst_rtsp_media_new () +
+GstElement * + +gst_rtsp_media_get_element () +
+void + +gst_rtsp_media_take_pipeline () +
+void + +gst_rtsp_media_set_permissions () +
+GstRTSPPermissions * + +gst_rtsp_media_get_permissions () +
+void + +gst_rtsp_media_set_shared () +
+gboolean + +gst_rtsp_media_is_shared () +
+void + +gst_rtsp_media_set_reusable () +
+gboolean + +gst_rtsp_media_is_reusable () +
+void + +gst_rtsp_media_set_profiles () +
+GstRTSPProfile + +gst_rtsp_media_get_profiles () +
+void + +gst_rtsp_media_set_protocols () +
+GstRTSPLowerTrans + +gst_rtsp_media_get_protocols () +
+void + +gst_rtsp_media_set_eos_shutdown () +
+gboolean + +gst_rtsp_media_is_eos_shutdown () +
+void + +gst_rtsp_media_set_address_pool () +
+GstRTSPAddressPool * + +gst_rtsp_media_get_address_pool () +
+void + +gst_rtsp_media_set_buffer_size () +
+guint + +gst_rtsp_media_get_buffer_size () +
+gboolean + +gst_rtsp_media_setup_sdp () +
+gboolean + +gst_rtsp_media_prepare () +
+gboolean + +gst_rtsp_media_unprepare () +
+GstRTSPMediaStatus + +gst_rtsp_media_get_status () +
+void + +gst_rtsp_media_set_suspend_mode () +
+GstRTSPSuspendMode + +gst_rtsp_media_get_suspend_mode () +
+gboolean + +gst_rtsp_media_suspend () +
+gboolean + +gst_rtsp_media_unsuspend () +
+void + +gst_rtsp_media_collect_streams () +
+GstRTSPStream * + +gst_rtsp_media_create_stream () +
+guint + +gst_rtsp_media_n_streams () +
+GstRTSPStream * + +gst_rtsp_media_get_stream () +
+GstRTSPStream * + +gst_rtsp_media_find_stream () +
+gboolean + +gst_rtsp_media_seek () +
+gchar * + +gst_rtsp_media_get_range_string () +
+gboolean + +gst_rtsp_media_set_state () +
+void + +gst_rtsp_media_set_pipeline_state () +
+GstClock * + +gst_rtsp_media_get_clock () +
+GstClockTime + +gst_rtsp_media_get_base_time () +
+void + +gst_rtsp_media_use_time_provider () +
+gboolean + +gst_rtsp_media_is_time_provider () +
+GstNetTimeProvider * + +gst_rtsp_media_get_time_provider () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
guintbuffer-sizeRead / Write
+GstElement *elementRead / Write / Construct Only
gbooleaneos-shutdownRead / Write
GstRTSPProfileprofilesRead / Write
GstRTSPLowerTransprotocolsRead / Write
gbooleanreusableRead / Write
gbooleansharedRead / Write
GstRTSPSuspendModesuspend-modeRead / Write
gbooleantime-providerRead / Write
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
voidnew-stateRun Last
voidnew-streamRun Last
voidpreparedRun Last
voidremoved-streamRun Last
voidtarget-stateRun Last
voidunpreparedRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + +
structGstRTSPMedia
structGstRTSPMediaClass
enumGstRTSPMediaStatus
enumGstRTSPSuspendMode
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GstRTSPMedia
+
+
+
+

Description

+

a GstRTSPMedia contains the complete GStreamer pipeline to manage the +streaming to the clients. The actual data transfer is done by the +GstRTSPStream objects that are created and exposed by the GstRTSPMedia.

+

The GstRTSPMedia is usually created from a GstRTSPMediaFactory when the +client does a DESCRIBE or SETUP of a resource.

+

A media is created with gst_rtsp_media_new() that takes the element that will +provide the streaming elements. For each of the streams, a new GstRTSPStream +object needs to be made with the gst_rtsp_media_create_stream() which takes +the payloader element and the source pad that produces the RTP stream.

+

The pipeline of the media is set to PAUSED with gst_rtsp_media_prepare(). The +prepare method will add rtpbin and sinks and sources to send and receive RTP +and RTCP packets from the clients. Each stream srcpad is connected to an +input into the internal rtpbin.

+

It is also possible to dynamically create GstRTSPStream objects during the +prepare phase. With gst_rtsp_media_get_status() you can check the status of +the prepare phase.

+

After the media is prepared, it is ready for streaming. It will usually be +managed in a session with gst_rtsp_session_manage_media(). See +GstRTSPSession and GstRTSPSessionMedia.

+

The state of the media can be controlled with gst_rtsp_media_set_state(). +Seeking can be done with gst_rtsp_media_seek().

+

With gst_rtsp_media_unprepare() the pipeline is stopped and shut down. When +gst_rtsp_media_set_eos_shutdown() an EOS will be sent to the pipeline to +cleanly shut down.

+

With gst_rtsp_media_set_shared(), the media can be shared between multiple +clients. With gst_rtsp_media_set_reusable() you can control if the pipeline +can be prepared again after an unprepare.

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_media_new ()

+
GstRTSPMedia *
+gst_rtsp_media_new (GstElement *element);
+

Create a new GstRTSPMedia instance. element + is the bin element that +provides the different streams. The GstRTSPMedia object contains the +element to produce RTP data for one or more related (audio/video/..) +streams.

+

Ownership is taken of element +.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement.

[transfer full]
+
+
+

Returns

+

a new GstRTSPMedia object.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_get_element ()

+
GstElement *
+gst_rtsp_media_get_element (GstRTSPMedia *media);
+

Get the element that was used when constructing media +.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

a GstElement. Unref after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_take_pipeline ()

+
void
+gst_rtsp_media_take_pipeline (GstRTSPMedia *media,
+                              GstPipeline *pipeline);
+

Set pipeline + as the GstPipeline for media +. Ownership is +taken of pipeline +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

pipeline

a GstPipeline.

[transfer full]
+
+
+
+
+

gst_rtsp_media_set_permissions ()

+
void
+gst_rtsp_media_set_permissions (GstRTSPMedia *media,
+                                GstRTSPPermissions *permissions);
+

Set permissions + on media +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

permissions

a GstRTSPPermissions.

[transfer none]
+
+
+
+
+

gst_rtsp_media_get_permissions ()

+
GstRTSPPermissions *
+gst_rtsp_media_get_permissions (GstRTSPMedia *media);
+

Get the permissions object from media +.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

a GstRTSPPermissions object, unref after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_set_shared ()

+
void
+gst_rtsp_media_set_shared (GstRTSPMedia *media,
+                           gboolean shared);
+

Set or unset if the pipeline for media + can be shared will multiple clients. +When shared + is TRUE, client requests for this media will share the media +pipeline.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

shared

the new value

 
+
+
+
+
+

gst_rtsp_media_is_shared ()

+
gboolean
+gst_rtsp_media_is_shared (GstRTSPMedia *media);
+

Check if the pipeline for media + can be shared between multiple clients.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

TRUE if the media can be shared between clients.

+

+
+
+
+
+

gst_rtsp_media_set_reusable ()

+
void
+gst_rtsp_media_set_reusable (GstRTSPMedia *media,
+                             gboolean reusable);
+

Set or unset if the pipeline for media + can be reused after the pipeline has +been unprepared.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

reusable

the new value

 
+
+
+
+
+

gst_rtsp_media_is_reusable ()

+
gboolean
+gst_rtsp_media_is_reusable (GstRTSPMedia *media);
+

Check if the pipeline for media + can be reused after an unprepare.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

TRUE if the media can be reused

+

+
+
+
+
+

gst_rtsp_media_set_profiles ()

+
void
+gst_rtsp_media_set_profiles (GstRTSPMedia *media,
+                             GstRTSPProfile profiles);
+

Configure the allowed lower transport for media +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

profiles

the new flags

 
+
+
+
+
+

gst_rtsp_media_get_profiles ()

+
GstRTSPProfile
+gst_rtsp_media_get_profiles (GstRTSPMedia *media);
+

Get the allowed profiles of media +.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

a GstRTSPProfile

+

+
+
+
+
+

gst_rtsp_media_set_protocols ()

+
void
+gst_rtsp_media_set_protocols (GstRTSPMedia *media,
+                              GstRTSPLowerTrans protocols);
+

Configure the allowed lower transport for media +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

protocols

the new flags

 
+
+
+
+
+

gst_rtsp_media_get_protocols ()

+
GstRTSPLowerTrans
+gst_rtsp_media_get_protocols (GstRTSPMedia *media);
+

Get the allowed protocols of media +.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

a GstRTSPLowerTrans

+

+
+
+
+
+

gst_rtsp_media_set_eos_shutdown ()

+
void
+gst_rtsp_media_set_eos_shutdown (GstRTSPMedia *media,
+                                 gboolean eos_shutdown);
+

Set or unset if an EOS event will be sent to the pipeline for media + before +it is unprepared.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

eos_shutdown

the new value

 
+
+
+
+
+

gst_rtsp_media_is_eos_shutdown ()

+
gboolean
+gst_rtsp_media_is_eos_shutdown (GstRTSPMedia *media);
+

Check if the pipeline for media + will send an EOS down the pipeline before +unpreparing.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

TRUE if the media will send EOS before unpreparing.

+

+
+
+
+
+

gst_rtsp_media_set_address_pool ()

+
void
+gst_rtsp_media_set_address_pool (GstRTSPMedia *media,
+                                 GstRTSPAddressPool *pool);
+

configure pool + to be used as the address pool of media +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

pool

a GstRTSPAddressPool.

[transfer none]
+
+
+
+
+

gst_rtsp_media_get_address_pool ()

+
GstRTSPAddressPool *
+gst_rtsp_media_get_address_pool (GstRTSPMedia *media);
+

Get the GstRTSPAddressPool used as the address pool of media +.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

the GstRTSPAddressPool of media +. g_object_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_set_buffer_size ()

+
void
+gst_rtsp_media_set_buffer_size (GstRTSPMedia *media,
+                                guint size);
+

Set the kernel UDP buffer size.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

size

the new value

 
+
+
+
+
+

gst_rtsp_media_get_buffer_size ()

+
guint
+gst_rtsp_media_get_buffer_size (GstRTSPMedia *media);
+

Get the kernel UDP buffer size.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

the kernel UDP buffer size.

+

+
+
+
+
+

gst_rtsp_media_setup_sdp ()

+
gboolean
+gst_rtsp_media_setup_sdp (GstRTSPMedia *media,
+                          GstSDPMessage *sdp,
+                          GstSDPInfo *info);
+

Add media + specific info to sdp +. info + is used to configure the connection +information in the SDP.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

media

a GstRTSPMedia

 

sdp

a GstSDPMessage.

[transfer none]

info

a GstSDPInfo.

[transfer none]
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

gst_rtsp_media_prepare ()

+
gboolean
+gst_rtsp_media_prepare (GstRTSPMedia *media,
+                        GstRTSPThread *thread);
+

Prepare media + for streaming. This function will create the objects +to manage the streaming. A pipeline must have been set on media + with +gst_rtsp_media_take_pipeline().

+

It will preroll the pipeline and collect vital information about the streams +such as the duration.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

thread

a GstRTSPThread to run the +bus handler or NULL.

[transfer full][allow-none]
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

gst_rtsp_media_unprepare ()

+
gboolean
+gst_rtsp_media_unprepare (GstRTSPMedia *media);
+

Unprepare media +. After this call, the media should be prepared again before +it can be used again. If the media is set to be non-reusable, a new instance +must be created.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

gst_rtsp_media_get_status ()

+
GstRTSPMediaStatus
+gst_rtsp_media_get_status (GstRTSPMedia *media);
+

Get the status of media +. When media + is busy preparing, this function waits +until media + is prepared or in error.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

the status of media +.

+

+
+
+
+
+

gst_rtsp_media_set_suspend_mode ()

+
void
+gst_rtsp_media_set_suspend_mode (GstRTSPMedia *media,
+                                 GstRTSPSuspendMode mode);
+

Control how @ media will be suspended after the SDP has been generated and +after a PAUSE request has been performed.

+

Media must be unprepared when setting the suspend mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

mode

the new GstRTSPSuspendMode

 
+
+
+
+
+

gst_rtsp_media_get_suspend_mode ()

+
GstRTSPSuspendMode
+gst_rtsp_media_get_suspend_mode (GstRTSPMedia *media);
+

Get how media + will be suspended.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

GstRTSPSuspendMode.

+

+
+
+
+
+

gst_rtsp_media_suspend ()

+
gboolean
+gst_rtsp_media_suspend (GstRTSPMedia *media);
+

Suspend media +. The state of the pipeline managed by media + is set to +GST_STATE_NULL but all streams are kept. media + can be prepared again +with gst_rtsp_media_unsuspend()

+

media + must be prepared with gst_rtsp_media_prepare();

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

gst_rtsp_media_unsuspend ()

+
gboolean
+gst_rtsp_media_unsuspend (GstRTSPMedia *media);
+

Unsuspend media + if it was in a suspended state. This method does nothing +when the media was not in the suspended state.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

gst_rtsp_media_collect_streams ()

+
void
+gst_rtsp_media_collect_streams (GstRTSPMedia *media);
+

Find all payloader elements, they should be named pay%d in the +element of media +, and create GstRTSPStreams for them.

+

Collect all dynamic elements, named dynpay%d, and add them to +the list of dynamic elements.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+
+
+

gst_rtsp_media_create_stream ()

+
GstRTSPStream *
+gst_rtsp_media_create_stream (GstRTSPMedia *media,
+                              GstElement *payloader,
+                              GstPad *srcpad);
+

Create a new stream in media + that provides RTP data on srcpad +. +srcpad + should be a pad of an element inside media->element +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

media

a GstRTSPMedia

 

payloader

a GstElement

 

srcpad

a source GstPad

 
+
+
+

Returns

+

a new GstRTSPStream that remains valid for as long +as media +exists.

+

[transfer none]

+
+
+
+
+

gst_rtsp_media_n_streams ()

+
guint
+gst_rtsp_media_n_streams (GstRTSPMedia *media);
+

Get the number of streams in this media.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

The number of streams.

+

+
+
+
+
+

gst_rtsp_media_get_stream ()

+
GstRTSPStream *
+gst_rtsp_media_get_stream (GstRTSPMedia *media,
+                           guint idx);
+

Retrieve the stream with index idx + from media +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

idx

the stream index

 
+
+
+

Returns

+

the GstRTSPStream at index +idx +or NULL when a stream with that index did not exist.

+

[nullable][transfer none]

+
+
+
+
+

gst_rtsp_media_find_stream ()

+
GstRTSPStream *
+gst_rtsp_media_find_stream (GstRTSPMedia *media,
+                            const gchar *control);
+

Find a stream in media + with control + as the control uri.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

control

the control of the stream

 
+
+
+

Returns

+

the GstRTSPStream with +control uri control +or NULL when a stream with that control did +not exist.

+

[nullable][transfer none]

+
+
+
+
+

gst_rtsp_media_seek ()

+
gboolean
+gst_rtsp_media_seek (GstRTSPMedia *media,
+                     GstRTSPTimeRange *range);
+

Seek the pipeline of media + to range +. media + must be prepared with +gst_rtsp_media_prepare().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

range

a GstRTSPTimeRange.

[transfer none]
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

gst_rtsp_media_get_range_string ()

+
gchar *
+gst_rtsp_media_get_range_string (GstRTSPMedia *media,
+                                 gboolean play,
+                                 GstRTSPRangeUnit unit);
+

Get the current range as a string. media + must be prepared with +gst_rtsp_media_prepare().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

media

a GstRTSPMedia

 

play

for the PLAY request

 

unit

the unit to use for the string

 
+
+
+

Returns

+

The range as a string, g_free() after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_set_state ()

+
gboolean
+gst_rtsp_media_set_state (GstRTSPMedia *media,
+                          GstState state,
+                          GPtrArray *transports);
+

Set the state of media + to state + and for the transports in transports +.

+

media + must be prepared with gst_rtsp_media_prepare();

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

media

a GstRTSPMedia

 

state

the target state of the media

 

transports

a GPtrArray of GstRTSPStreamTransport pointers.

[transfer none][element-type GstRtspServer.RTSPStreamTransport]
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

gst_rtsp_media_set_pipeline_state ()

+
void
+gst_rtsp_media_set_pipeline_state (GstRTSPMedia *media,
+                                   GstState state);
+

Set the state of the pipeline managed by media + to state +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

state

the target state of the pipeline

 
+
+
+
+
+

gst_rtsp_media_get_clock ()

+
GstClock *
+gst_rtsp_media_get_clock (GstRTSPMedia *media);
+

Get the clock that is used by the pipeline in media +.

+

media + must be prepared before this method returns a valid clock object.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

the GstClock used by media +. unref after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_get_base_time ()

+
GstClockTime
+gst_rtsp_media_get_base_time (GstRTSPMedia *media);
+

Get the base_time that is used by the pipeline in media +.

+

media + must be prepared before this method returns a valid base_time.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

the base_time used by media +.

+

+
+
+
+
+

gst_rtsp_media_use_time_provider ()

+
void
+gst_rtsp_media_use_time_provider (GstRTSPMedia *media,
+                                  gboolean time_provider);
+

Set media + to provide a GstNetTimeProvider.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPMedia

 

time_provider

if a GstNetTimeProvider should be used

 
+
+
+
+
+

gst_rtsp_media_is_time_provider ()

+
gboolean
+gst_rtsp_media_is_time_provider (GstRTSPMedia *media);
+

Check if media + can provide a GstNetTimeProvider for its pipeline clock.

+

Use gst_rtsp_media_get_time_provider() to get the network clock.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPMedia

 
+
+
+

Returns

+

TRUE if media +can provide a GstNetTimeProvider.

+

+
+
+
+
+

gst_rtsp_media_get_time_provider ()

+
GstNetTimeProvider *
+gst_rtsp_media_get_time_provider (GstRTSPMedia *media,
+                                  const gchar *address,
+                                  guint16 port);
+

Get the GstNetTimeProvider for the clock used by media +. The time provider +will listen on address + and port + for client time requests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

media

a GstRTSPMedia

 

address

an address or NULL.

[allow-none]

port

a port or 0

 
+
+
+

Returns

+

the GstNetTimeProvider of media +.

+

[transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstRTSPMedia

+
struct GstRTSPMedia;
+

A class that contains the GStreamer element along with a list of +GstRTSPStream objects that can produce data.

+

This object is usually created from a GstRTSPMediaFactory.

+
+
+
+

struct GstRTSPMediaClass

+
struct GstRTSPMediaClass {
+  GObjectClass  parent_class;
+
+  /* vmethods */
+  gboolean        (*handle_message)  (GstRTSPMedia *media, GstMessage *message);
+  gboolean        (*prepare)         (GstRTSPMedia *media, GstRTSPThread *thread);
+  gboolean        (*unprepare)       (GstRTSPMedia *media);
+  gboolean        (*suspend)         (GstRTSPMedia *media);
+  gboolean        (*unsuspend)       (GstRTSPMedia *media);
+  gboolean        (*convert_range)   (GstRTSPMedia *media, GstRTSPTimeRange *range,
+                                      GstRTSPRangeUnit unit);
+  gboolean        (*query_position)  (GstRTSPMedia *media, gint64 *position);
+  gboolean        (*query_stop)      (GstRTSPMedia *media, gint64 *stop);
+  GstElement *    (*create_rtpbin)   (GstRTSPMedia *media);
+  gboolean        (*setup_rtpbin)    (GstRTSPMedia *media, GstElement *rtpbin);
+  gboolean        (*setup_sdp)       (GstRTSPMedia *media, GstSDPMessage *sdp, GstSDPInfo *info);
+
+  /* signals */
+  void            (*new_stream)      (GstRTSPMedia *media, GstRTSPStream * stream);
+  void            (*removed_stream)  (GstRTSPMedia *media, GstRTSPStream * stream);
+
+  void            (*prepared)        (GstRTSPMedia *media);
+  void            (*unprepared)      (GstRTSPMedia *media);
+
+  void            (*target_state)    (GstRTSPMedia *media, GstState state);
+  void            (*new_state)       (GstRTSPMedia *media, GstState state);
+};
+
+

The RTSP media class

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GObjectClass parent_class;

  

handle_message ()

handle a message

 

prepare ()

the default implementation adds all elements and sets the +pipeline's state to GST_STATE_PAUSED (or GST_STATE_PLAYING +in case of NO_PREROLL elements).

 

unprepare ()

the default implementation sets the pipeline's state +to GST_STATE_NULL and removes all elements.

 

suspend ()

the default implementation sets the pipeline's state to +GST_STATE_NULL GST_STATE_PAUSED depending on the selected +suspend mode.

 

unsuspend ()

the default implementation reverts the suspend operation. +The pipeline will be prerolled again if it's state was +set to GST_STATE_NULL in suspend.

 

convert_range ()

convert a range to the given unit

 

query_position ()

query the current position in the pipeline

 

query_stop ()

query when playback will stop

 

create_rtpbin ()

  

setup_rtpbin ()

  

setup_sdp ()

  

new_stream ()

  

removed_stream ()

  

prepared ()

  

unprepared ()

  

target_state ()

  

new_state ()

  
+
+
+
+
+

enum GstRTSPMediaStatus

+

The state of the media pipeline.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_RTSP_MEDIA_STATUS_UNPREPARED

+

media pipeline not prerolled

+
 

GST_RTSP_MEDIA_STATUS_UNPREPARING

+

media pipeline is busy doing a clean + shutdown.

+
 

GST_RTSP_MEDIA_STATUS_PREPARING

+

media pipeline is prerolling

+
 

GST_RTSP_MEDIA_STATUS_PREPARED

+

media pipeline is prerolled

+
 

GST_RTSP_MEDIA_STATUS_SUSPENDED

+

media is suspended

+
 

GST_RTSP_MEDIA_STATUS_ERROR

+

media pipeline is in error

+
 
+
+
+
+
+

enum GstRTSPSuspendMode

+

The suspend mode of the media pipeline. A media pipeline is suspended right +after creating the SDP and when the client performs a PAUSED request.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_RTSP_SUSPEND_MODE_NONE

+

Media is not suspended

+
 

GST_RTSP_SUSPEND_MODE_PAUSE

+

Media is PAUSED in suspend

+
 

GST_RTSP_SUSPEND_MODE_RESET

+

The media is set to NULL when suspended

+
 
+
+
+
+
+

Property Details

+
+

The “buffer-size” property

+
  “buffer-size”              guint
+

The kernel UDP buffer size to use.

+

Flags: Read / Write

+

Default value: 524288

+
+
+
+

The “element” property

+
  “element”                  GstElement *
+

The GstBin to use for streaming the media.

+

Flags: Read / Write / Construct Only

+
+
+
+

The “eos-shutdown” property

+
  “eos-shutdown”             gboolean
+

Send an EOS event to the pipeline before unpreparing.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “profiles” property

+
  “profiles”                 GstRTSPProfile
+

Allowed transfer profiles.

+

Flags: Read / Write

+

Default value: GST_RTSP_PROFILE_AVP

+
+
+
+

The “protocols” property

+
  “protocols”                GstRTSPLowerTrans
+

Allowed lower transport protocols.

+

Flags: Read / Write

+

Default value: GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | GST_RTSP_LOWER_TRANS_TCP

+
+
+
+

The “reusable” property

+
  “reusable”                 gboolean
+

If this media pipeline can be reused after an unprepare.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “shared” property

+
  “shared”                   gboolean
+

If this media pipeline can be shared.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “suspend-mode” property

+
  “suspend-mode”             GstRTSPSuspendMode
+

How to suspend the media in PAUSED.

+

Flags: Read / Write

+

Default value: GST_RTSP_SUSPEND_MODE_NONE

+
+
+
+

The “time-provider” property

+
  “time-provider”            gboolean
+

Use a NetTimeProvider for clients.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

Signal Details

+
+

The “new-state” signal

+
void
+user_function (GstRTSPMedia *gstrtspmedia,
+               gint          arg1,
+               gpointer      user_data)
+

Flags: Run Last

+
+
+
+

The “new-stream” signal

+
void
+user_function (GstRTSPMedia  *gstrtspmedia,
+               GstRTSPStream *arg1,
+               gpointer       user_data)
+

Flags: Run Last

+
+
+
+

The “prepared” signal

+
void
+user_function (GstRTSPMedia *gstrtspmedia,
+               gpointer      user_data)
+

Flags: Run Last

+
+
+
+

The “removed-stream” signal

+
void
+user_function (GstRTSPMedia  *gstrtspmedia,
+               GstRTSPStream *arg1,
+               gpointer       user_data)
+

Flags: Run Last

+
+
+
+

The “target-state” signal

+
void
+user_function (GstRTSPMedia *gstrtspmedia,
+               gint          arg1,
+               gpointer      user_data)
+

Flags: Run Last

+
+
+
+

The “unprepared” signal

+
void
+user_function (GstRTSPMedia *gstrtspmedia,
+               gpointer      user_data)
+

Flags: Run Last

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstRTSPMediaFactory.html b/docs/libs/html/GstRTSPMediaFactory.html new file mode 100644 index 0000000..703b800 --- /dev/null +++ b/docs/libs/html/GstRTSPMediaFactory.html @@ -0,0 +1,1201 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPMediaFactory + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPMediaFactory

+

GstRTSPMediaFactory — A factory for media pipelines

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPMediaFactory * + +gst_rtsp_media_factory_new () +
+gchar * + +gst_rtsp_media_factory_get_launch () +
+void + +gst_rtsp_media_factory_set_launch () +
+GstRTSPPermissions * + +gst_rtsp_media_factory_get_permissions () +
+void + +gst_rtsp_media_factory_set_permissions () +
+void + +gst_rtsp_media_factory_add_role () +
+void + +gst_rtsp_media_factory_set_shared () +
+gboolean + +gst_rtsp_media_factory_is_shared () +
+gboolean + +gst_rtsp_media_factory_is_eos_shutdown () +
+void + +gst_rtsp_media_factory_set_eos_shutdown () +
+GstRTSPLowerTrans + +gst_rtsp_media_factory_get_protocols () +
+void + +gst_rtsp_media_factory_set_protocols () +
+void + +gst_rtsp_media_factory_set_profiles () +
+GstRTSPProfile + +gst_rtsp_media_factory_get_profiles () +
+GstRTSPAddressPool * + +gst_rtsp_media_factory_get_address_pool () +
+void + +gst_rtsp_media_factory_set_address_pool () +
+guint + +gst_rtsp_media_factory_get_buffer_size () +
+void + +gst_rtsp_media_factory_set_buffer_size () +
+GstRTSPSuspendMode + +gst_rtsp_media_factory_get_suspend_mode () +
+void + +gst_rtsp_media_factory_set_suspend_mode () +
+GstRTSPMedia * + +gst_rtsp_media_factory_construct () +
+GstElement * + +gst_rtsp_media_factory_create_element () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
guintbuffer-sizeRead / Write
gbooleaneos-shutdownRead / Write
+gchar *launchRead / Write
GstRTSPProfileprofilesRead / Write
GstRTSPLowerTransprotocolsRead / Write
gbooleansharedRead / Write
GstRTSPSuspendModesuspend-modeRead / Write
+
+
+

Signals

+
+++++ + + + + + + + + + + + + +
voidmedia-configureRun Last
voidmedia-constructedRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstRTSPMediaFactory
structGstRTSPMediaFactoryClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GstRTSPMediaFactory
+
+
+
+

Description

+

The GstRTSPMediaFactory is responsible for creating or recycling +GstRTSPMedia objects based on the passed URL.

+

The default implementation of the object can create GstRTSPMedia objects +containing a pipeline created from a launch description set with +gst_rtsp_media_factory_set_launch().

+

Media from a factory can be shared by setting the shared flag with +gst_rtsp_media_factory_set_shared(). When a factory is shared, +gst_rtsp_media_factory_construct() will return the same GstRTSPMedia when +the url matches.

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_media_factory_new ()

+
GstRTSPMediaFactory *
+gst_rtsp_media_factory_new (void);
+

Create a new GstRTSPMediaFactory instance.

+
+

Returns

+

a new GstRTSPMediaFactory object.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_factory_get_launch ()

+
gchar *
+gst_rtsp_media_factory_get_launch (GstRTSPMediaFactory *factory);
+

Get the gst_parse_launch() pipeline description that will be used in the +default prepare vmethod.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstRTSPMediaFactory

 
+
+
+

Returns

+

the configured launch description. g_free() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_factory_set_launch ()

+
void
+gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory *factory,
+                                   const gchar *launch);
+

The gst_parse_launch() line to use for constructing the pipeline in the +default prepare vmethod.

+

The pipeline description should return a GstBin as the toplevel element +which can be accomplished by enclosing the dscription with brackets '(' +')'.

+

The description should return a pipeline with payloaders named pay0, pay1, +etc.. Each of the payloaders will result in a stream.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

launch

the launch description

 
+
+
+
+
+

gst_rtsp_media_factory_get_permissions ()

+
GstRTSPPermissions *
+gst_rtsp_media_factory_get_permissions
+                               (GstRTSPMediaFactory *factory);
+

Get the permissions object from factory +.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstRTSPMediaFactory

 
+
+
+

Returns

+

a GstRTSPPermissions object, unref after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_factory_set_permissions ()

+
void
+gst_rtsp_media_factory_set_permissions
+                               (GstRTSPMediaFactory *factory,
+                                GstRTSPPermissions *permissions);
+

Set permissions + on factory +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

permissions

a GstRTSPPermissions.

[transfer none]
+
+
+
+
+

gst_rtsp_media_factory_add_role ()

+
void
+gst_rtsp_media_factory_add_role (GstRTSPMediaFactory *factory,
+                                 const gchar *role,
+                                 const gchar *fieldname,
+                                 ...);
+

A convenience method to add role + with fieldname + and additional arguments to +the permissions of factory +. If factory + had no permissions, new permissions +will be created and the role will be added to it.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

role

a role

 

fieldname

the first field name

 

...

additional arguments

 
+
+
+
+
+

gst_rtsp_media_factory_set_shared ()

+
void
+gst_rtsp_media_factory_set_shared (GstRTSPMediaFactory *factory,
+                                   gboolean shared);
+

Configure if media created from this factory can be shared between clients.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

shared

the new value

 
+
+
+
+
+

gst_rtsp_media_factory_is_shared ()

+
gboolean
+gst_rtsp_media_factory_is_shared (GstRTSPMediaFactory *factory);
+

Get if media created from this factory can be shared between clients.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstRTSPMediaFactory

 
+
+
+

Returns

+

TRUE if the media will be shared between clients.

+

+
+
+
+
+

gst_rtsp_media_factory_is_eos_shutdown ()

+
gboolean
+gst_rtsp_media_factory_is_eos_shutdown
+                               (GstRTSPMediaFactory *factory);
+

Get if media created from this factory will have an EOS event sent to the +pipeline before shutdown.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstRTSPMediaFactory

 
+
+
+

Returns

+

TRUE if the media will receive EOS before shutdown.

+

+
+
+
+
+

gst_rtsp_media_factory_set_eos_shutdown ()

+
void
+gst_rtsp_media_factory_set_eos_shutdown
+                               (GstRTSPMediaFactory *factory,
+                                gboolean eos_shutdown);
+

Configure if media created from this factory will have an EOS sent to the +pipeline before shutdown.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

eos_shutdown

the new value

 
+
+
+
+
+

gst_rtsp_media_factory_get_protocols ()

+
GstRTSPLowerTrans
+gst_rtsp_media_factory_get_protocols (GstRTSPMediaFactory *factory);
+

Get the allowed protocols of factory +.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstRTSPMediaFactory

 
+
+
+

Returns

+

a GstRTSPLowerTrans

+

+
+
+
+
+

gst_rtsp_media_factory_set_protocols ()

+
void
+gst_rtsp_media_factory_set_protocols (GstRTSPMediaFactory *factory,
+                                      GstRTSPLowerTrans protocols);
+

Configure the allowed lower transport for factory +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

protocols

the new flags

 
+
+
+
+
+

gst_rtsp_media_factory_set_profiles ()

+
void
+gst_rtsp_media_factory_set_profiles (GstRTSPMediaFactory *factory,
+                                     GstRTSPProfile profiles);
+

Configure the allowed profiles for factory +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

profiles

the new flags

 
+
+
+
+
+

gst_rtsp_media_factory_get_profiles ()

+
GstRTSPProfile
+gst_rtsp_media_factory_get_profiles (GstRTSPMediaFactory *factory);
+

Get the allowed profiles of factory +.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstRTSPMediaFactory

 
+
+
+

Returns

+

a GstRTSPProfile

+

+
+
+
+
+

gst_rtsp_media_factory_get_address_pool ()

+
GstRTSPAddressPool *
+gst_rtsp_media_factory_get_address_pool
+                               (GstRTSPMediaFactory *factory);
+

Get the GstRTSPAddressPool used as the address pool of factory +.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstRTSPMediaFactory

 
+
+
+

Returns

+

the GstRTSPAddressPool of factory +. g_object_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_factory_set_address_pool ()

+
void
+gst_rtsp_media_factory_set_address_pool
+                               (GstRTSPMediaFactory *factory,
+                                GstRTSPAddressPool *pool);
+

configure pool + to be used as the address pool of factory +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

pool

a GstRTSPAddressPool.

[transfer none]
+
+
+
+
+

gst_rtsp_media_factory_get_buffer_size ()

+
guint
+gst_rtsp_media_factory_get_buffer_size
+                               (GstRTSPMediaFactory *factory);
+

Get the kernel UDP buffer size.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstRTSPMedia

 
+
+
+

Returns

+

the kernel UDP buffer size.

+

+
+
+
+
+

gst_rtsp_media_factory_set_buffer_size ()

+
void
+gst_rtsp_media_factory_set_buffer_size
+                               (GstRTSPMediaFactory *factory,
+                                guint size);
+

Set the kernel UDP buffer size.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMedia

 

size

the new value

 
+
+
+
+
+

gst_rtsp_media_factory_get_suspend_mode ()

+
GstRTSPSuspendMode
+gst_rtsp_media_factory_get_suspend_mode
+                               (GstRTSPMediaFactory *factory);
+

Get how media created from this factory will be suspended.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstRTSPMediaFactory

 
+
+
+

Returns

+

a GstRTSPSuspendMode.

+

+
+
+
+
+

gst_rtsp_media_factory_set_suspend_mode ()

+
void
+gst_rtsp_media_factory_set_suspend_mode
+                               (GstRTSPMediaFactory *factory,
+                                GstRTSPSuspendMode mode);
+

Configure how media created from this factory will be suspended.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

mode

the new GstRTSPSuspendMode

 
+
+
+
+
+

gst_rtsp_media_factory_construct ()

+
GstRTSPMedia *
+gst_rtsp_media_factory_construct (GstRTSPMediaFactory *factory,
+                                  const GstRTSPUrl *url);
+

Construct the media object and create its streams. Implementations +should create the needed gstreamer elements and add them to the result +object. No state changes should be performed on them yet.

+

One or more GstRTSPStream objects should be created from the result +with gst_rtsp_media_create_stream().

+

After the media is constructed, it can be configured and then prepared +with gst_rtsp_media_prepare().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

url

the url used

 
+
+
+

Returns

+

a new GstRTSPMedia if the media could be prepared.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_factory_create_element ()

+
GstElement *
+gst_rtsp_media_factory_create_element (GstRTSPMediaFactory *factory,
+                                       const GstRTSPUrl *url);
+

Construct and return a GstElement that is a GstBin containing +the elements to use for streaming the media.

+

The bin should contain payloaders pay%d for each stream. The default +implementation of this function returns the bin created from the +launch parameter.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

url

the url used

 
+
+
+

Returns

+

a new GstElement.

+

[transfer floating]

+
+
+
+
+

Types and Values

+
+

struct GstRTSPMediaFactory

+
struct GstRTSPMediaFactory;
+

The definition and logic for constructing the pipeline for a media. The media +can contain multiple streams like audio and video.

+
+
+
+

struct GstRTSPMediaFactoryClass

+
struct GstRTSPMediaFactoryClass {
+  GObjectClass  parent_class;
+
+  gchar *         (*gen_key)            (GstRTSPMediaFactory *factory, const GstRTSPUrl *url);
+
+  GstElement *    (*create_element)     (GstRTSPMediaFactory *factory, const GstRTSPUrl *url);
+  GstRTSPMedia *  (*construct)          (GstRTSPMediaFactory *factory, const GstRTSPUrl *url);
+  GstElement *    (*create_pipeline)    (GstRTSPMediaFactory *factory, GstRTSPMedia *media);
+  void            (*configure)          (GstRTSPMediaFactory *factory, GstRTSPMedia *media);
+
+  /* signals */
+  void            (*media_constructed)  (GstRTSPMediaFactory *factory, GstRTSPMedia *media);
+  void            (*media_configure)    (GstRTSPMediaFactory *factory, GstRTSPMedia *media);
+};
+
+

The GstRTSPMediaFactory class structure.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GObjectClass parent_class;

  

gen_key ()

convert url +to a key for caching shared GstRTSPMedia objects. +The default implementation of this function will use the complete URL +including the query parameters to return a key.

 

create_element ()

Construct and return a GstElement that is a GstBin containing +the elements to use for streaming the media. The bin should contain +payloaders pay%d for each stream. The default implementation of this +function returns the bin created from the launch parameter.

 

construct ()

the vmethod that will be called when the factory has to create the +GstRTSPMedia for url +. The default implementation of this +function calls create_element to retrieve an element and then looks for +pay%d to create the streams.

 

create_pipeline ()

create a new pipeline or re-use an existing one and +add the GstRTSPMedia's element created by construct +to the pipeline.

 

configure ()

configure the media created with construct +. The default +implementation will configure the 'shared' property of the media.

 

media_constructed ()

signal emited when a media was constructed

 

media_configure ()

signal emited when a media should be configured

 
+
+
+
+
+

Property Details

+
+

The “buffer-size” property

+
  “buffer-size”              guint
+

The kernel UDP buffer size to use.

+

Flags: Read / Write

+

Default value: 524288

+
+
+
+

The “eos-shutdown” property

+
  “eos-shutdown”             gboolean
+

Send EOS down the pipeline before shutting down.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “launch” property

+
  “launch”                   gchar *
+

A launch description of the pipeline.

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “profiles” property

+
  “profiles”                 GstRTSPProfile
+

Allowed transfer profiles.

+

Flags: Read / Write

+

Default value: GST_RTSP_PROFILE_AVP

+
+
+
+

The “protocols” property

+
  “protocols”                GstRTSPLowerTrans
+

Allowed lower transport protocols.

+

Flags: Read / Write

+

Default value: GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | GST_RTSP_LOWER_TRANS_TCP

+
+
+
+

The “shared” property

+
  “shared”                   gboolean
+

If media from this factory is shared.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “suspend-mode” property

+
  “suspend-mode”             GstRTSPSuspendMode
+

Control how media will be suspended.

+

Flags: Read / Write

+

Default value: GST_RTSP_SUSPEND_MODE_NONE

+
+
+
+

Signal Details

+
+

The “media-configure” signal

+
void
+user_function (GstRTSPMediaFactory *gstrtspmediafactory,
+               GstRTSPMedia        *arg1,
+               gpointer             user_data)
+

Flags: Run Last

+
+
+
+

The “media-constructed” signal

+
void
+user_function (GstRTSPMediaFactory *gstrtspmediafactory,
+               GstRTSPMedia        *arg1,
+               gpointer             user_data)
+

Flags: Run Last

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstRTSPMountPoints.html b/docs/libs/html/GstRTSPMountPoints.html new file mode 100644 index 0000000..a685b7b --- /dev/null +++ b/docs/libs/html/GstRTSPMountPoints.html @@ -0,0 +1,353 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPMountPoints + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPMountPoints

+

GstRTSPMountPoints — Map a path to media

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPMountPoints * + +gst_rtsp_mount_points_new () +
+void + +gst_rtsp_mount_points_add_factory () +
+void + +gst_rtsp_mount_points_remove_factory () +
+GstRTSPMediaFactory * + +gst_rtsp_mount_points_match () +
+gchar * + +gst_rtsp_mount_points_make_path () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstRTSPMountPoints
structGstRTSPMountPointsClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GstRTSPMountPoints
+
+
+
+

Description

+

A GstRTSPMountPoints object maintains a relation between paths +and GstRTSPMediaFactory objects. This object is usually given to +GstRTSPClient and used to find the media attached to a path.

+

With gst_rtsp_mount_points_add_factory() and +gst_rtsp_mount_points_remove_factory(), factories can be added and +removed.

+

With gst_rtsp_mount_points_match() you can find the GstRTSPMediaFactory +object that completely matches the given path.

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_mount_points_new ()

+
GstRTSPMountPoints *
+gst_rtsp_mount_points_new (void);
+

Make a new mount points object.

+
+

Returns

+

a new GstRTSPMountPoints.

+

[transfer full]

+
+
+
+
+

gst_rtsp_mount_points_add_factory ()

+
void
+gst_rtsp_mount_points_add_factory (GstRTSPMountPoints *mounts,
+                                   const gchar *path,
+                                   GstRTSPMediaFactory *factory);
+

Attach factory + to the mount point path + in mounts +.

+

path + is of the form (/node)+. Any previous mount point will be freed.

+

Ownership is taken of the reference on factory + so that factory + should not be +used after calling this function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mounts

a GstRTSPMountPoints

 

path

a mount point

 

factory

a GstRTSPMediaFactory.

[transfer full]
+
+
+
+
+

gst_rtsp_mount_points_remove_factory ()

+
void
+gst_rtsp_mount_points_remove_factory (GstRTSPMountPoints *mounts,
+                                      const gchar *path);
+

Remove the GstRTSPMediaFactory associated with path + in mounts +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

mounts

a GstRTSPMountPoints

 

path

a mount point

 
+
+
+
+
+

gst_rtsp_mount_points_match ()

+
GstRTSPMediaFactory *
+gst_rtsp_mount_points_match (GstRTSPMountPoints *mounts,
+                             const gchar *path,
+                             gint *matched);
+

Find the factory in mounts + that has the longest match with path +.

+

If matched + is NULL, path + will match the factory exactly otherwise +the amount of characters that matched is returned in matched +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mounts

a GstRTSPMountPoints

 

path

a mount point

 

matched

the amount of path +matched.

[out][allow-none]
+
+
+

Returns

+

the GstRTSPMediaFactory for path +. +g_object_unref() after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_mount_points_make_path ()

+
gchar *
+gst_rtsp_mount_points_make_path (GstRTSPMountPoints *mounts,
+                                 const GstRTSPUrl *url);
+

Make a path string from url +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

mounts

a GstRTSPMountPoints

 

url

a GstRTSPUrl

 
+
+
+

Returns

+

a path string for url +, g_free() after usage.

+

[transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstRTSPMountPoints

+
struct GstRTSPMountPoints;
+

Creates a GstRTSPMediaFactory object for a given url.

+
+
+
+

struct GstRTSPMountPointsClass

+
struct GstRTSPMountPointsClass {
+  GObjectClass  parent_class;
+
+  gchar * (*make_path) (GstRTSPMountPoints *mounts,
+                        const GstRTSPUrl *url);
+};
+
+

The class for the media mounts object.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GObjectClass parent_class;

  

make_path ()

make a path from the given url.

 
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstRTSPServer.html b/docs/libs/html/GstRTSPServer.html new file mode 100644 index 0000000..e9547e9 --- /dev/null +++ b/docs/libs/html/GstRTSPServer.html @@ -0,0 +1,1302 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPServer + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPServer

+

GstRTSPServer — The main server object

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPServer * + +gst_rtsp_server_new () +
+gchar * + +gst_rtsp_server_get_address () +
+void + +gst_rtsp_server_set_address () +
+gchar * + +gst_rtsp_server_get_service () +
+void + +gst_rtsp_server_set_service () +
+gint + +gst_rtsp_server_get_backlog () +
+void + +gst_rtsp_server_set_backlog () +
+int + +gst_rtsp_server_get_bound_port () +
+GstRTSPMountPoints * + +gst_rtsp_server_get_mount_points () +
+void + +gst_rtsp_server_set_mount_points () +
+GstRTSPSessionPool * + +gst_rtsp_server_get_session_pool () +
+void + +gst_rtsp_server_set_session_pool () +
+GstRTSPThreadPool * + +gst_rtsp_server_get_thread_pool () +
+void + +gst_rtsp_server_set_thread_pool () +
+GstRTSPAuth * + +gst_rtsp_server_get_auth () +
+void + +gst_rtsp_server_set_auth () +
+gboolean + +gst_rtsp_server_transfer_connection () +
+gboolean + +gst_rtsp_server_io_func () +
+GSocket * + +gst_rtsp_server_create_socket () +
+GSource * + +gst_rtsp_server_create_source () +
+guint + +gst_rtsp_server_attach () +
+GstRTSPFilterResult + +(*GstRTSPServerClientFilterFunc) () +
+GList * + +gst_rtsp_server_client_filter () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gchar *addressRead / Write
gintbacklogRead / Write
gintbound-portRead
+GstRTSPMountPoints *mount-pointsRead / Write
+gchar *serviceRead / Write
+GstRTSPSessionPool *session-poolRead / Write
+
+
+

Signals

+
+++++ + + + + + +
voidclient-connectedRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstRTSPServer
structGstRTSPServerClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GstRTSPServer
+
+
+
+

Description

+

The server object is the object listening for connections on a port and +creating GstRTSPClient objects to handle those connections.

+

The server will listen on the address set with gst_rtsp_server_set_address() +and the port or service configured with gst_rtsp_server_set_service(). +Use gst_rtsp_server_set_backlog() to configure the amount of pending requests +that the server will keep. By default the server listens on the current +network (0.0.0.0) and port 8554.

+

The server will require an SSL connection when a TLS certificate has been +set in the auth object with gst_rtsp_auth_set_tls_certificate().

+

To start the server, use gst_rtsp_server_attach() to attach it to a +GMainContext. For more control, gst_rtsp_server_create_source() and +gst_rtsp_server_create_socket() can be used to get a GSource and GSocket +respectively.

+

gst_rtsp_server_transfer_connection() can be used to transfer an existing +socket to the RTSP server, for example from an HTTP server.

+

Once the server socket is attached to a mainloop, it will start accepting +connections. When a new connection is received, a new GstRTSPClient object +is created to handle the connection. The new client will be configured with +the server GstRTSPAuth, GstRTSPMountPoints, GstRTSPSessionPool and +GstRTSPThreadPool.

+

The server uses the configured GstRTSPThreadPool object to handle the +remainder of the communication with this client.

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_server_new ()

+
GstRTSPServer *
+gst_rtsp_server_new (void);
+

Create a new GstRTSPServer instance.

+
+

Returns

+

a new GstRTSPServer.

+

[transfer full]

+
+
+
+
+

gst_rtsp_server_get_address ()

+
gchar *
+gst_rtsp_server_get_address (GstRTSPServer *server);
+

Get the address on which the server will accept connections.

+
+

Parameters

+
+++++ + + + + + +

server

a GstRTSPServer

 
+
+
+

Returns

+

the server address. g_free() after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_server_set_address ()

+
void
+gst_rtsp_server_set_address (GstRTSPServer *server,
+                             const gchar *address);
+

Configure server + to accept connections on the given address.

+

This function must be called before the server is bound.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a GstRTSPServer

 

address

the address

 
+
+
+
+
+

gst_rtsp_server_get_service ()

+
gchar *
+gst_rtsp_server_get_service (GstRTSPServer *server);
+

Get the service on which the server will accept connections.

+
+

Parameters

+
+++++ + + + + + +

server

a GstRTSPServer

 
+
+
+

Returns

+

the service. use g_free() after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_server_set_service ()

+
void
+gst_rtsp_server_set_service (GstRTSPServer *server,
+                             const gchar *service);
+

Configure server + to accept connections on the given service. +service + should be a string containing the service name (see services(5)) or +a string containing a port number between 1 and 65535.

+

When service + is set to "0", the server will listen on a random free +port. The actual used port can be retrieved with +gst_rtsp_server_get_bound_port().

+

This function must be called before the server is bound.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a GstRTSPServer

 

service

the service

 
+
+
+
+
+

gst_rtsp_server_get_backlog ()

+
gint
+gst_rtsp_server_get_backlog (GstRTSPServer *server);
+

The maximum amount of queued requests for the server.

+
+

Parameters

+
+++++ + + + + + +

server

a GstRTSPServer

 
+
+
+

Returns

+

the server backlog.

+

+
+
+
+
+

gst_rtsp_server_set_backlog ()

+
void
+gst_rtsp_server_set_backlog (GstRTSPServer *server,
+                             gint backlog);
+

configure the maximum amount of requests that may be queued for the +server.

+

This function must be called before the server is bound.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a GstRTSPServer

 

backlog

the backlog

 
+
+
+
+
+

gst_rtsp_server_get_bound_port ()

+
int
+gst_rtsp_server_get_bound_port (GstRTSPServer *server);
+

Get the port number where the server was bound to.

+
+

Parameters

+
+++++ + + + + + +

server

a GstRTSPServer

 
+
+
+

Returns

+

the port number

+

+
+
+
+
+

gst_rtsp_server_get_mount_points ()

+
GstRTSPMountPoints *
+gst_rtsp_server_get_mount_points (GstRTSPServer *server);
+

Get the GstRTSPMountPoints used as the mount points of server +.

+
+

Parameters

+
+++++ + + + + + +

server

a GstRTSPServer

 
+
+
+

Returns

+

the GstRTSPMountPoints of server +. g_object_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_server_set_mount_points ()

+
void
+gst_rtsp_server_set_mount_points (GstRTSPServer *server,
+                                  GstRTSPMountPoints *mounts);
+

configure mounts + to be used as the mount points of server +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a GstRTSPServer

 

mounts

a GstRTSPMountPoints.

[transfer none]
+
+
+
+
+

gst_rtsp_server_get_session_pool ()

+
GstRTSPSessionPool *
+gst_rtsp_server_get_session_pool (GstRTSPServer *server);
+

Get the GstRTSPSessionPool used as the session pool of server +.

+
+

Parameters

+
+++++ + + + + + +

server

a GstRTSPServer

 
+
+
+

Returns

+

the GstRTSPSessionPool used for sessions. g_object_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_server_set_session_pool ()

+
void
+gst_rtsp_server_set_session_pool (GstRTSPServer *server,
+                                  GstRTSPSessionPool *pool);
+

configure pool + to be used as the session pool of server +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a GstRTSPServer

 

pool

a GstRTSPSessionPool.

[transfer none]
+
+
+
+
+

gst_rtsp_server_get_thread_pool ()

+
GstRTSPThreadPool *
+gst_rtsp_server_get_thread_pool (GstRTSPServer *server);
+

Get the GstRTSPThreadPool used as the thread pool of server +.

+
+

Parameters

+
+++++ + + + + + +

server

a GstRTSPServer

 
+
+
+

Returns

+

the GstRTSPThreadPool of server +. g_object_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_server_set_thread_pool ()

+
void
+gst_rtsp_server_set_thread_pool (GstRTSPServer *server,
+                                 GstRTSPThreadPool *pool);
+

configure pool + to be used as the thread pool of server +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a GstRTSPServer

 

pool

a GstRTSPThreadPool.

[transfer none]
+
+
+
+
+

gst_rtsp_server_get_auth ()

+
GstRTSPAuth *
+gst_rtsp_server_get_auth (GstRTSPServer *server);
+

Get the GstRTSPAuth used as the authentication manager of server +.

+
+

Parameters

+
+++++ + + + + + +

server

a GstRTSPServer

 
+
+
+

Returns

+

the GstRTSPAuth of server +. g_object_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_server_set_auth ()

+
void
+gst_rtsp_server_set_auth (GstRTSPServer *server,
+                          GstRTSPAuth *auth);
+

configure auth + to be used as the authentication manager of server +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a GstRTSPServer

 

auth

a GstRTSPAuth.

[transfer none]
+
+
+
+
+

gst_rtsp_server_transfer_connection ()

+
gboolean
+gst_rtsp_server_transfer_connection (GstRTSPServer *server,
+                                     GSocket *socket,
+                                     const gchar *ip,
+                                     gint port,
+                                     const gchar *initial_buffer);
+

Take an existing network socket and use it for an RTSP connection. This +is used when transferring a socket from an HTTP server which should be used +as an RTSP over HTTP tunnel. The initial_buffer + contains any remaining data +that the HTTP server read from the socket while parsing the HTTP header.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

server

a GstRTSPServer

 

socket

a network socket.

[transfer full]

ip

the IP address of the remote client

 

port

the port used by the other end

 

initial_buffer

any initial data that was already read from the socket

 
+
+
+

Returns

+

TRUE if all was ok, FALSE if an error occurred.

+

+
+
+
+
+

gst_rtsp_server_io_func ()

+
gboolean
+gst_rtsp_server_io_func (GSocket *socket,
+                         GIOCondition condition,
+                         GstRTSPServer *server);
+

A default GSocketSourceFunc that creates a new GstRTSPClient to accept and handle a +new connection on socket + or server +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

socket

a GSocket

 

condition

the condition on source +

 

server

a GstRTSPServer.

[transfer none]
+
+
+

Returns

+

TRUE if the source could be connected, FALSE if an error occurred.

+

+
+
+
+
+

gst_rtsp_server_create_socket ()

+
GSocket *
+gst_rtsp_server_create_socket (GstRTSPServer *server,
+                               GCancellable *cancellable,
+                               GError **error);
+

Create a GSocket for server +. The socket will listen on the +configured service.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

server

a GstRTSPServer

 

cancellable

a GCancellable.

[allow-none]

error

a GError.

[out]
+
+
+

Returns

+

the GSocket for server +or NULL when an error +occurred.

+

[transfer full]

+
+
+
+
+

gst_rtsp_server_create_source ()

+
GSource *
+gst_rtsp_server_create_source (GstRTSPServer *server,
+                               GCancellable *cancellable,
+                               GError **error);
+

Create a GSource for server +. The new source will have a default +GSocketSourceFunc of gst_rtsp_server_io_func().

+

cancellable + if not NULL can be used to cancel the source, which will cause +the source to trigger, reporting the current condition (which is likely 0 +unless cancellation happened at the same time as a condition change). You can +check for this in the callback using g_cancellable_is_cancelled().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

server

a GstRTSPServer

 

cancellable

a GCancellable or NULL.

[allow-none]

error

a GError.

[out]
+
+
+

Returns

+

the GSource for server +or NULL when an error +occurred. Free with g_source_unref().

+

[transfer full]

+
+
+
+
+

gst_rtsp_server_attach ()

+
guint
+gst_rtsp_server_attach (GstRTSPServer *server,
+                        GMainContext *context);
+

Attaches server + to context +. When the mainloop for context + is run, the +server will be dispatched. When context + is NULL, the default context will be +used).

+

This function should be called when the server properties and urls are fully +configured and the server is ready to start.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a GstRTSPServer

 

context

a GMainContext.

[allow-none]
+
+
+

Returns

+

the ID (greater than 0) for the source within the GMainContext.

+

+
+
+
+
+

GstRTSPServerClientFilterFunc ()

+
GstRTSPFilterResult
+(*GstRTSPServerClientFilterFunc) (GstRTSPServer *server,
+                                  GstRTSPClient *client,
+                                  gpointer user_data);
+

This function will be called by the gst_rtsp_server_client_filter(). An +implementation should return a value of GstRTSPFilterResult.

+

When this function returns GST_RTSP_FILTER_REMOVE, client + will be removed +from server +.

+

A return value of GST_RTSP_FILTER_KEEP will leave client + untouched in +server +.

+

A value of GST_RTSP_FILTER_REF will add client + to the result GList of +gst_rtsp_server_client_filter().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

server

a GstRTSPServer object

 

client

a GstRTSPClient in server +

 

user_data

user data that has been given to gst_rtsp_server_client_filter()

 
+
+
+

Returns

+

a GstRTSPFilterResult.

+

+
+
+
+
+

gst_rtsp_server_client_filter ()

+
GList *
+gst_rtsp_server_client_filter (GstRTSPServer *server,
+                               GstRTSPServerClientFilterFunc func,
+                               gpointer user_data);
+

Call func + for each client managed by server +. The result value of func + +determines what happens to the client. func + will be called with server + +locked so no further actions on server + can be performed from func +.

+

If func + returns GST_RTSP_FILTER_REMOVE, the client will be removed from +server +.

+

If func + returns GST_RTSP_FILTER_KEEP, the client will remain in server +.

+

If func + returns GST_RTSP_FILTER_REF, the client will remain in server + but +will also be added with an additional ref to the result GList of this +function..

+

When func + is NULL, GST_RTSP_FILTER_REF will be assumed for each client.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

server

a GstRTSPServer

 

func

a callback.

[scope call][allow-none]

user_data

user data passed to func +

 
+
+
+

Returns

+

a GList with all +clients for which func +returned GST_RTSP_FILTER_REF. After usage, each +element in the GList should be unreffed before the list is freed.

+

[element-type GstRTSPClient][transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstRTSPServer

+
struct GstRTSPServer;
+

This object listens on a port, creates and manages the clients connected to +it.

+
+
+
+

struct GstRTSPServerClass

+
struct GstRTSPServerClass {
+  GObjectClass  parent_class;
+
+  GstRTSPClient * (*create_client)      (GstRTSPServer *server);
+
+  /* signals */
+  void            (*client_connected)   (GstRTSPServer *server, GstRTSPClient *client);
+};
+
+

The RTSP server class structure

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GObjectClass parent_class;

  

create_client ()

Create, configure a new GstRTSPClient +object that handles the new connection on socket +. The default +implementation will create a GstRTSPClient and will configure the +mount-points, auth, session-pool and thread-pool on the client.

 

client_connected ()

emited when a new client connected.

 
+
+
+
+
+

Property Details

+
+

The “address” property

+
  “address”                  gchar *
+

The address the server uses to listen on.

+

Flags: Read / Write

+

Default value: "0.0.0.0"

+
+
+
+

The “backlog” property

+
  “backlog”                  gint
+

The maximum length to which the queue of pending connections may grow.

+

Flags: Read / Write

+

Allowed values: >= 0

+

Default value: 5

+
+
+
+

The “bound-port” property

+
  “bound-port”               gint
+

The port number the server is listening on.

+

Flags: Read

+

Allowed values: [-1,65535]

+

Default value: -1

+
+
+
+

The “mount-points” property

+
  “mount-points”             GstRTSPMountPoints *
+

The mount points to use for client session.

+

Flags: Read / Write

+
+
+
+

The “service” property

+
  “service”                  gchar *
+

The service or port number the server uses to listen on.

+

Flags: Read / Write

+

Default value: "8554"

+
+
+
+

The “session-pool” property

+
  “session-pool”             GstRTSPSessionPool *
+

The session pool to use for client session.

+

Flags: Read / Write

+
+
+
+

Signal Details

+
+

The “client-connected” signal

+
void
+user_function (GstRTSPServer *gstrtspserver,
+               GstRTSPClient *arg1,
+               gpointer       user_data)
+

Flags: Run Last

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstRTSPSession.html b/docs/libs/html/GstRTSPSession.html new file mode 100644 index 0000000..38cc654 --- /dev/null +++ b/docs/libs/html/GstRTSPSession.html @@ -0,0 +1,881 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPSession + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPSession

+

GstRTSPSession — An object to manage media

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPSession * + +gst_rtsp_session_new () +
const gchar * + +gst_rtsp_session_get_sessionid () +
+gchar * + +gst_rtsp_session_get_header () +
+void + +gst_rtsp_session_set_timeout () +
+guint + +gst_rtsp_session_get_timeout () +
+void + +gst_rtsp_session_touch () +
+void + +gst_rtsp_session_prevent_expire () +
+void + +gst_rtsp_session_allow_expire () +
+gint + +gst_rtsp_session_next_timeout () +
+gboolean + +gst_rtsp_session_is_expired () +
+GstRTSPSessionMedia * + +gst_rtsp_session_manage_media () +
+gboolean + +gst_rtsp_session_release_media () +
+GstRTSPSessionMedia * + +gst_rtsp_session_get_media () +
+GstRTSPFilterResult + +(*GstRTSPSessionFilterFunc) () +
+GList * + +gst_rtsp_session_filter () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + +
+gchar *sessionidRead / Write / Construct Only
guinttimeoutRead / Write
gbooleantimeout-always-visibleRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structGstRTSPSession
structGstRTSPSessionClass
enumGstRTSPFilterResult
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GstRTSPSession
+
+
+
+

Description

+

The GstRTSPSession is identified by an id, unique in the +GstRTSPSessionPool that created the session and manages media and its +configuration.

+

A GstRTSPSession has a timeout that can be retrieved with +gst_rtsp_session_get_timeout(). You can check if the sessions is expired with +gst_rtsp_session_is_expired(). gst_rtsp_session_touch() will reset the +expiration counter of the session.

+

When a client configures a media with SETUP, a session will be created to +keep track of the configuration of that media. With +gst_rtsp_session_manage_media(), the media is added to the managed media +in the session. With gst_rtsp_session_release_media() the media can be +released again from the session. Managed media is identified in the sessions +with a url. Use gst_rtsp_session_get_media() to get the media that matches +(part of) the given url.

+

The media in a session can be iterated with gst_rtsp_session_filter().

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_session_new ()

+
GstRTSPSession *
+gst_rtsp_session_new (const gchar *sessionid);
+

Create a new GstRTSPSession instance with sessionid +.

+
+

Parameters

+
+++++ + + + + + +

sessionid

a session id

 
+
+
+

Returns

+

a new GstRTSPSession.

+

[transfer full]

+
+
+
+
+

gst_rtsp_session_get_sessionid ()

+
const gchar *
+gst_rtsp_session_get_sessionid (GstRTSPSession *session);
+

Get the sessionid of session +.

+
+

Parameters

+
+++++ + + + + + +

session

a GstRTSPSession

 
+
+
+

Returns

+

the sessionid of session +. The value remains valid +as long as session +is alive.

+

[transfer none]

+
+
+
+
+

gst_rtsp_session_get_header ()

+
gchar *
+gst_rtsp_session_get_header (GstRTSPSession *session);
+

Get the string that can be placed in the Session header field.

+
+

Parameters

+
+++++ + + + + + +

session

a GstRTSPSession

 
+
+
+

Returns

+

the Session header of session +. g_free() after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_session_set_timeout ()

+
void
+gst_rtsp_session_set_timeout (GstRTSPSession *session,
+                              guint timeout);
+

Configure session + for a timeout of timeout + seconds. The session will be +cleaned up when there is no activity for timeout + seconds.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a GstRTSPSession

 

timeout

the new timeout

 
+
+
+
+
+

gst_rtsp_session_get_timeout ()

+
guint
+gst_rtsp_session_get_timeout (GstRTSPSession *session);
+

Get the timeout value of session +.

+
+

Parameters

+
+++++ + + + + + +

session

a GstRTSPSession

 
+
+
+

Returns

+

the timeout of session +in seconds.

+

+
+
+
+
+

gst_rtsp_session_touch ()

+
void
+gst_rtsp_session_touch (GstRTSPSession *session);
+

Update the last_access time of the session to the current time.

+
+

Parameters

+
+++++ + + + + + +

session

a GstRTSPSession

 
+
+
+
+
+

gst_rtsp_session_prevent_expire ()

+
void
+gst_rtsp_session_prevent_expire (GstRTSPSession *session);
+

Prevent session + from expiring.

+
+

Parameters

+
+++++ + + + + + +

session

a GstRTSPSession

 
+
+
+
+
+

gst_rtsp_session_allow_expire ()

+
void
+gst_rtsp_session_allow_expire (GstRTSPSession *session);
+

Allow session + to expire. This method must be called an equal +amount of time as gst_rtsp_session_prevent_expire().

+
+

Parameters

+
+++++ + + + + + +

session

a GstRTSPSession

 
+
+
+
+
+

gst_rtsp_session_next_timeout ()

+
gint
+gst_rtsp_session_next_timeout (GstRTSPSession *session,
+                               GTimeVal *now);
+

Get the amount of milliseconds till the session will expire.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a GstRTSPSession

 

now

the current system time.

[transfer none]
+
+
+

Returns

+

the amount of milliseconds since the session will time out.

+

+
+
+
+
+

gst_rtsp_session_is_expired ()

+
gboolean
+gst_rtsp_session_is_expired (GstRTSPSession *session,
+                             GTimeVal *now);
+

Check if session + timeout out.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a GstRTSPSession

 

now

the current system time.

[transfer none]
+
+
+

Returns

+

TRUE if session +timed out

+

+
+
+
+
+

gst_rtsp_session_manage_media ()

+
GstRTSPSessionMedia *
+gst_rtsp_session_manage_media (GstRTSPSession *sess,
+                               const gchar *path,
+                               GstRTSPMedia *media);
+

Manage the media object obj + in sess +. path + will be used to retrieve this +media from the session with gst_rtsp_session_get_media().

+

Ownership is taken from media +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

sess

a GstRTSPSession

 

path

the path for the media

 

media

a GstRTSPMedia.

[transfer full]
+
+
+

Returns

+

a new GstRTSPSessionMedia +object.

+

[transfer none]

+
+
+
+
+

gst_rtsp_session_release_media ()

+
gboolean
+gst_rtsp_session_release_media (GstRTSPSession *sess,
+                                GstRTSPSessionMedia *media);
+

Release the managed media + in sess +, freeing the memory allocated by it.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sess

a GstRTSPSession

 

media

a GstRTSPMedia.

[transfer none]
+
+
+

Returns

+

TRUE if there are more media session left in sess +.

+

+
+
+
+
+

gst_rtsp_session_get_media ()

+
GstRTSPSessionMedia *
+gst_rtsp_session_get_media (GstRTSPSession *sess,
+                            const gchar *path,
+                            gint *matched);
+

Get the session media for path +. matched + will contain the number of matched +characters of path +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

sess

a GstRTSPSession

 

path

the path for the media

 

matched

the amount of matched characters.

[out]
+
+
+

Returns

+

the configuration for path +in sess +.

+

[transfer none]

+
+
+
+
+

GstRTSPSessionFilterFunc ()

+
GstRTSPFilterResult
+(*GstRTSPSessionFilterFunc) (GstRTSPSession *sess,
+                             GstRTSPSessionMedia *media,
+                             gpointer user_data);
+

This function will be called by the gst_rtsp_session_filter(). An +implementation should return a value of GstRTSPFilterResult.

+

When this function returns GST_RTSP_FILTER_REMOVE, media + will be removed +from sess +.

+

A return value of GST_RTSP_FILTER_KEEP will leave media + untouched in +sess +.

+

A value of GST_RTSP_FILTER_REF will add media + to the result GList of +gst_rtsp_session_filter().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

sess

a GstRTSPSession object

 

media

a GstRTSPSessionMedia in sess +

 

user_data

user data that has been given to gst_rtsp_session_filter()

 
+
+
+

Returns

+

a GstRTSPFilterResult.

+

+
+
+
+
+

gst_rtsp_session_filter ()

+
GList *
+gst_rtsp_session_filter (GstRTSPSession *sess,
+                         GstRTSPSessionFilterFunc func,
+                         gpointer user_data);
+

Call func + for each media in sess +. The result value of func + determines +what happens to the media. func + will be called with sess + +locked so no further actions on sess + can be performed from func +.

+

If func + returns GST_RTSP_FILTER_REMOVE, the media will be removed from +sess +.

+

If func + returns GST_RTSP_FILTER_KEEP, the media will remain in sess +.

+

If func + returns GST_RTSP_FILTER_REF, the media will remain in sess + but +will also be added with an additional ref to the result GList of this +function..

+

When func + is NULL, GST_RTSP_FILTER_REF will be assumed for all media.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

sess

a GstRTSPSession

 

func

a callback.

[scope call][allow-none]

user_data

user data passed to func +.

[closure]
+
+
+

Returns

+

a GList with all +media for which func +returned GST_RTSP_FILTER_REF. After usage, each +element in the GList should be unreffed before the list is freed.

+

[element-type GstRTSPSessionMedia][transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstRTSPSession

+
struct GstRTSPSession;
+

Session information kept by the server for a specific client. +One client session, identified with a session id, can handle multiple medias +identified with the url of a media.

+
+
+
+

struct GstRTSPSessionClass

+
struct GstRTSPSessionClass {
+  GObjectClass  parent_class;
+};
+
+
+
+
+

enum GstRTSPFilterResult

+

Possible return values for gst_rtsp_session_pool_filter().

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_RTSP_FILTER_REMOVE

+

Remove session

+
 

GST_RTSP_FILTER_KEEP

+

Keep session in the pool

+
 

GST_RTSP_FILTER_REF

+

Ref session in the result list

+
 
+
+
+
+
+

Property Details

+
+

The “sessionid” property

+
  “sessionid”                gchar *
+

the session id.

+

Flags: Read / Write / Construct Only

+

Default value: NULL

+
+
+
+

The “timeout” property

+
  “timeout”                  guint
+

the timeout of the session (0 = never).

+

Flags: Read / Write

+

Default value: 60

+
+
+
+

The “timeout-always-visible” property

+
  “timeout-always-visible”   gboolean
+

timeout always visible in header.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstRTSPSessionPool.html b/docs/libs/html/GstRTSPSessionPool.html new file mode 100644 index 0000000..718aef7 --- /dev/null +++ b/docs/libs/html/GstRTSPSessionPool.html @@ -0,0 +1,730 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPSessionPool + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPSessionPool

+

GstRTSPSessionPool — An object for managing sessions

+
+
+

Functions

+ +
+
+

Properties

+
+++++ + + + + + +
guintmax-sessionsRead / Write
+
+
+

Signals

+
+++++ + + + + + +
voidsession-removedRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstRTSPSessionPool
structGstRTSPSessionPoolClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GstRTSPSessionPool
+
+
+
+

Description

+

The GstRTSPSessionPool object manages a list of GstRTSPSession objects.

+

The maximum number of sessions can be configured with +gst_rtsp_session_pool_set_max_sessions(). The current number of sessions can +be retrieved with gst_rtsp_session_pool_get_n_sessions().

+

Use gst_rtsp_session_pool_create() to create a new GstRTSPSession object. +The session object can be found again with its id and +gst_rtsp_session_pool_find().

+

All sessions can be iterated with gst_rtsp_session_pool_filter().

+

Run gst_rtsp_session_pool_cleanup() periodically to remove timed out sessions +or use gst_rtsp_session_pool_create_watch() to be notified when session +cleanup should be performed.

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_session_pool_new ()

+
GstRTSPSessionPool *
+gst_rtsp_session_pool_new (void);
+

Create a new GstRTSPSessionPool instance.

+
+

Returns

+

A new GstRTSPSessionPool. g_object_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_session_pool_get_max_sessions ()

+
guint
+gst_rtsp_session_pool_get_max_sessions
+                               (GstRTSPSessionPool *pool);
+

Get the maximum allowed number of sessions in pool +. 0 means an unlimited +amount of sessions.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstRTSPSessionPool

 
+
+
+

Returns

+

the maximum allowed number of sessions.

+

+
+
+
+
+

gst_rtsp_session_pool_set_max_sessions ()

+
void
+gst_rtsp_session_pool_set_max_sessions
+                               (GstRTSPSessionPool *pool,
+                                guint max);
+

Configure the maximum allowed number of sessions in pool + to max +. +A value of 0 means an unlimited amount of sessions.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

a GstRTSPSessionPool

 

max

the maximum number of sessions

 
+
+
+
+
+

gst_rtsp_session_pool_get_n_sessions ()

+
guint
+gst_rtsp_session_pool_get_n_sessions (GstRTSPSessionPool *pool);
+

Get the amount of active sessions in pool +.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstRTSPSessionPool

 
+
+
+

Returns

+

the amount of active sessions in pool +.

+

+
+
+
+
+

gst_rtsp_session_pool_create ()

+
GstRTSPSession *
+gst_rtsp_session_pool_create (GstRTSPSessionPool *pool);
+

Create a new GstRTSPSession object in pool +.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstRTSPSessionPool

 
+
+
+

Returns

+

a new GstRTSPSession.

+

[transfer full]

+
+
+
+
+

gst_rtsp_session_pool_find ()

+
GstRTSPSession *
+gst_rtsp_session_pool_find (GstRTSPSessionPool *pool,
+                            const gchar *sessionid);
+

Find the session with sessionid + in pool +. The access time of the session +will be updated with gst_rtsp_session_touch().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

the pool to search

 

sessionid

the session id

 
+
+
+

Returns

+

the GstRTSPSession with sessionid +or NULL when the session did not exist. g_object_unref() after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_rtsp_session_pool_remove ()

+
gboolean
+gst_rtsp_session_pool_remove (GstRTSPSessionPool *pool,
+                              GstRTSPSession *sess);
+

Remove sess + from pool +, releasing the ref that the pool has on sess +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

a GstRTSPSessionPool

 

sess

a GstRTSPSession.

[transfer none]
+
+
+

Returns

+

TRUE if the session was found and removed.

+

+
+
+
+
+

gst_rtsp_session_pool_cleanup ()

+
guint
+gst_rtsp_session_pool_cleanup (GstRTSPSessionPool *pool);
+

Inspect all the sessions in pool + and remove the sessions that are inactive +for more than their timeout.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstRTSPSessionPool

 
+
+
+

Returns

+

the amount of sessions that got removed.

+

+
+
+
+
+

GstRTSPSessionPoolFunc ()

+
gboolean
+(*GstRTSPSessionPoolFunc) (GstRTSPSessionPool *pool,
+                           gpointer user_data);
+

The function that will be called from the GSource watch on the session pool.

+

The function will be called when the pool must be cleaned up because one or +more sessions timed out.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

a GstRTSPSessionPool object

 

user_data

user data that has been given when registering the handler

 
+
+
+

Returns

+

FALSE if the source should be removed.

+

+
+
+
+
+

gst_rtsp_session_pool_create_watch ()

+
GSource *
+gst_rtsp_session_pool_create_watch (GstRTSPSessionPool *pool);
+

Create a GSource that will be dispatched when the session should be cleaned +up.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstRTSPSessionPool

 
+
+
+

Returns

+

a GSource.

+

[transfer full]

+
+
+
+
+

GstRTSPSessionPoolFilterFunc ()

+
GstRTSPFilterResult
+(*GstRTSPSessionPoolFilterFunc) (GstRTSPSessionPool *pool,
+                                 GstRTSPSession *session,
+                                 gpointer user_data);
+

This function will be called by the gst_rtsp_session_pool_filter(). An +implementation should return a value of GstRTSPFilterResult.

+

When this function returns GST_RTSP_FILTER_REMOVE, session + will be removed +from pool +.

+

A return value of GST_RTSP_FILTER_KEEP will leave session + untouched in +pool +.

+

A value of GST_RTSP_FILTER_REF will add session + to the result GList of +gst_rtsp_session_pool_filter().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pool

a GstRTSPSessionPool object

 

session

a GstRTSPSession in pool +

 

user_data

user data that has been given to gst_rtsp_session_pool_filter()

 
+
+
+

Returns

+

a GstRTSPFilterResult.

+

+
+
+
+
+

gst_rtsp_session_pool_filter ()

+
GList *
+gst_rtsp_session_pool_filter (GstRTSPSessionPool *pool,
+                              GstRTSPSessionPoolFilterFunc func,
+                              gpointer user_data);
+

Call func + for each session in pool +. The result value of func + determines +what happens to the session. func + will be called with the session pool +locked so no further actions on pool + can be performed from func +.

+

If func + returns GST_RTSP_FILTER_REMOVE, the session will be set to the +expired state with gst_rtsp_session_set_expired() and removed from +pool +.

+

If func + returns GST_RTSP_FILTER_KEEP, the session will remain in pool +.

+

If func + returns GST_RTSP_FILTER_REF, the session will remain in pool + but +will also be added with an additional ref to the result GList of this +function..

+

When func + is NULL, GST_RTSP_FILTER_REF will be assumed for all sessions.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pool

a GstRTSPSessionPool

 

func

a callback.

[scope call][allow-none]

user_data

user data passed to func +.

[closure]
+
+
+

Returns

+

a GList with all +sessions for which func +returned GST_RTSP_FILTER_REF. After usage, each +element in the GList should be unreffed before the list is freed.

+

[element-type GstRTSPSession][transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstRTSPSessionPool

+
struct GstRTSPSessionPool;
+

An object that keeps track of the active sessions. This object is usually +attached to a GstRTSPServer object to manage the sessions in that server.

+
+
+
+

struct GstRTSPSessionPoolClass

+
struct GstRTSPSessionPoolClass {
+  GObjectClass  parent_class;
+
+  gchar *          (*create_session_id)   (GstRTSPSessionPool *pool);
+  GstRTSPSession * (*create_session)      (GstRTSPSessionPool *pool, const gchar *id);
+
+  /* signals */
+  void             (*session_removed)     (GstRTSPSessionPool *pool,
+                                           GstRTSPSession *session);
+};
+
+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GObjectClass parent_class;

  

create_session_id ()

create a new random session id. Subclasses can create +custom session ids and should not check if the session exists.

 

create_session ()

make a new session object.

 

session_removed ()

a session was removed from the pool

 
+
+
+
+
+

Property Details

+
+

The “max-sessions” property

+
  “max-sessions”             guint
+

the maximum amount of sessions (0 = unlimited).

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

Signal Details

+
+

The “session-removed” signal

+
void
+user_function (GstRTSPSessionPool *gstrtspsessionpool,
+               GstRTSPSession     *arg1,
+               gpointer            user_data)
+

Flags: Run Last

+
+
+
+

See Also

+

GstRTSPSession

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstRTSPStream.html b/docs/libs/html/GstRTSPStream.html new file mode 100644 index 0000000..fee8a7d --- /dev/null +++ b/docs/libs/html/GstRTSPStream.html @@ -0,0 +1,1832 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPStream + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPStream

+

GstRTSPStream — A media stream

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPStream * + +gst_rtsp_stream_new () +
+guint + +gst_rtsp_stream_get_index () +
+GstPad * + +gst_rtsp_stream_get_srcpad () +
+gchar * + +gst_rtsp_stream_get_control () +
+void + +gst_rtsp_stream_set_control () +
+gboolean + +gst_rtsp_stream_has_control () +
+guint + +gst_rtsp_stream_get_mtu () +
+void + +gst_rtsp_stream_set_mtu () +
+gint + +gst_rtsp_stream_get_dscp_qos () +
+void + +gst_rtsp_stream_set_dscp_qos () +
+void + +gst_rtsp_stream_set_profiles () +
+GstRTSPProfile + +gst_rtsp_stream_get_profiles () +
+GstRTSPLowerTrans + +gst_rtsp_stream_get_protocols () +
+void + +gst_rtsp_stream_set_protocols () +
+gboolean + +gst_rtsp_stream_is_transport_supported () +
+GstRTSPAddressPool * + +gst_rtsp_stream_get_address_pool () +
+void + +gst_rtsp_stream_set_address_pool () +
+GstRTSPAddress * + +gst_rtsp_stream_reserve_address () +
+gboolean + +gst_rtsp_stream_join_bin () +
+gboolean + +gst_rtsp_stream_leave_bin () +
+void + +gst_rtsp_stream_get_server_port () +
+GstRTSPAddress * + +gst_rtsp_stream_get_multicast_address () +
+GObject * + +gst_rtsp_stream_get_rtpsession () +
+void + +gst_rtsp_stream_get_ssrc () +
+gboolean + +gst_rtsp_stream_get_rtpinfo () +
+GstCaps * + +gst_rtsp_stream_get_caps () +
+guint + +gst_rtsp_stream_get_pt () +
+GstFlowReturn + +gst_rtsp_stream_recv_rtcp () +
+GstFlowReturn + +gst_rtsp_stream_recv_rtp () +
+gboolean + +gst_rtsp_stream_add_transport () +
+gboolean + +gst_rtsp_stream_remove_transport () +
+GSocket * + +gst_rtsp_stream_get_rtp_socket () +
+GSocket * + +gst_rtsp_stream_get_rtcp_socket () +
+gboolean + +gst_rtsp_stream_set_blocked () +
+gboolean + +gst_rtsp_stream_is_blocking () +
+gboolean + +gst_rtsp_stream_update_crypto () +
+GstRTSPFilterResult + +(*GstRTSPStreamTransportFilterFunc) () +
+GList * + +gst_rtsp_stream_transport_filter () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstRTSPStream
 GstRTSPStreamClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GstRTSPStream
+
+
+
+

Description

+

The GstRTSPStream object manages the data transport for one stream. It +is created from a payloader element and a source pad that produce the RTP +packets for the stream.

+

With gst_rtsp_stream_join_bin() the streaming elements are added to the bin +and rtpbin. gst_rtsp_stream_leave_bin() removes the elements again.

+

The GstRTSPStream will use the configured addresspool, as set with +gst_rtsp_stream_set_address_pool(), to allocate multicast addresses for the +stream. With gst_rtsp_stream_get_multicast_address() you can get the +configured address.

+

With gst_rtsp_stream_get_server_port() you can get the port that the server +will use to receive RTCP. This is the part that the clients will use to send +RTCP to.

+

With gst_rtsp_stream_add_transport() destinations can be added where the +stream should be sent to. Use gst_rtsp_stream_remove_transport() to remove +the destination again.

+

Last reviewed on 2013-07-16 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_stream_new ()

+
GstRTSPStream *
+gst_rtsp_stream_new (guint idx,
+                     GstElement *payloader,
+                     GstPad *srcpad);
+

Create a new media stream with index idx + that handles RTP data on +srcpad + and has a payloader element payloader +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

idx

an index

 

srcpad

a GstPad

 

payloader

a GstElement

 
+
+
+

Returns

+

a new GstRTSPStream.

+

[transfer full]

+
+
+
+
+

gst_rtsp_stream_get_index ()

+
guint
+gst_rtsp_stream_get_index (GstRTSPStream *stream);
+

Get the stream index.

+

Return: the stream index.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+
+
+

gst_rtsp_stream_get_srcpad ()

+
GstPad *
+gst_rtsp_stream_get_srcpad (GstRTSPStream *stream);
+

Get the srcpad associated with stream +.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+

Returns

+

the srcpad. Unref after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_stream_get_control ()

+
gchar *
+gst_rtsp_stream_get_control (GstRTSPStream *stream);
+

Get the control string to identify this stream.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+

Returns

+

the control string. g_free() after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_stream_set_control ()

+
void
+gst_rtsp_stream_set_control (GstRTSPStream *stream,
+                             const gchar *control);
+

Set the control string in stream +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

control

a control string

 
+
+
+
+
+

gst_rtsp_stream_has_control ()

+
gboolean
+gst_rtsp_stream_has_control (GstRTSPStream *stream,
+                             const gchar *control);
+

Check if stream + has the control string control +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

control

a control string

 
+
+
+

Returns

+

TRUE is stream +has control +as the control string

+

+
+
+
+
+

gst_rtsp_stream_get_mtu ()

+
guint
+gst_rtsp_stream_get_mtu (GstRTSPStream *stream);
+

Get the configured MTU in the payloader of stream +.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+

Returns

+

the MTU of the payloader.

+

+
+
+
+
+

gst_rtsp_stream_set_mtu ()

+
void
+gst_rtsp_stream_set_mtu (GstRTSPStream *stream,
+                         guint mtu);
+

Configure the mtu in the payloader of stream + to mtu +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

mtu

a new MTU

 
+
+
+
+
+

gst_rtsp_stream_get_dscp_qos ()

+
gint
+gst_rtsp_stream_get_dscp_qos (GstRTSPStream *stream);
+

Get the configured DSCP QoS in of the outgoing sockets.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+

Returns

+

the DSCP QoS value of the outgoing sockets, or -1 if disbled.

+

+
+
+
+
+

gst_rtsp_stream_set_dscp_qos ()

+
void
+gst_rtsp_stream_set_dscp_qos (GstRTSPStream *stream,
+                              gint dscp_qos);
+

Configure the dscp qos of the outgoing sockets to dscp_qos +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

dscp_qos

a new dscp qos value (0-63, or -1 to disable)

 
+
+
+
+
+

gst_rtsp_stream_set_profiles ()

+
void
+gst_rtsp_stream_set_profiles (GstRTSPStream *stream,
+                              GstRTSPProfile profiles);
+

Configure the allowed profiles for stream +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

profiles

the new profiles

 
+
+
+
+
+

gst_rtsp_stream_get_profiles ()

+
GstRTSPProfile
+gst_rtsp_stream_get_profiles (GstRTSPStream *stream);
+

Get the allowed profiles of stream +.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+

Returns

+

a GstRTSPProfile

+

+
+
+
+
+

gst_rtsp_stream_get_protocols ()

+
GstRTSPLowerTrans
+gst_rtsp_stream_get_protocols (GstRTSPStream *stream);
+

Get the allowed protocols of stream +.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+

Returns

+

a GstRTSPLowerTrans

+

+
+
+
+
+

gst_rtsp_stream_set_protocols ()

+
void
+gst_rtsp_stream_set_protocols (GstRTSPStream *stream,
+                               GstRTSPLowerTrans protocols);
+

Configure the allowed lower transport for stream +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

protocols

the new flags

 
+
+
+
+
+

gst_rtsp_stream_is_transport_supported ()

+
gboolean
+gst_rtsp_stream_is_transport_supported
+                               (GstRTSPStream *stream,
+                                GstRTSPTransport *transport);
+

Check if transport + can be handled by stream

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

transport

a GstRTSPTransport.

[transfer none]
+
+
+

Returns

+

TRUE if transport +can be handled by stream +.

+

+
+
+
+
+

gst_rtsp_stream_get_address_pool ()

+
GstRTSPAddressPool *
+gst_rtsp_stream_get_address_pool (GstRTSPStream *stream);
+

Get the GstRTSPAddressPool used as the address pool of stream +.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+

Returns

+

the GstRTSPAddressPool of stream +. g_object_unref() after +usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_stream_set_address_pool ()

+
void
+gst_rtsp_stream_set_address_pool (GstRTSPStream *stream,
+                                  GstRTSPAddressPool *pool);
+

configure pool + to be used as the address pool of stream +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

pool

a GstRTSPAddressPool.

[transfer none]
+
+
+
+
+

gst_rtsp_stream_reserve_address ()

+
GstRTSPAddress *
+gst_rtsp_stream_reserve_address (GstRTSPStream *stream,
+                                 const gchar *address,
+                                 guint port,
+                                 guint n_ports,
+                                 guint ttl);
+

Reserve address + and port + as the address and port of stream +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

stream

a GstRTSPStream

 

address

an address

 

port

a port

 

n_ports

n_ports

 

ttl

a TTL

 
+
+
+

Returns

+

the GstRTSPAddress of stream +or NULL when +the address could be reserved. gst_rtsp_address_free() after usage.

+

[nullable]

+
+
+
+
+

gst_rtsp_stream_join_bin ()

+
gboolean
+gst_rtsp_stream_join_bin (GstRTSPStream *stream,
+                          GstBin *bin,
+                          GstElement *rtpbin,
+                          GstState state);
+

Join the GstBin bin + that contains the element rtpbin +.

+

stream + will link to rtpbin +, which must be inside bin +. The elements +added to bin + will be set to the state given in state +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

stream

a GstRTSPStream

 

bin

a GstBin to join.

[transfer none]

rtpbin

a rtpbin element in bin +.

[transfer none]

state

the target state of the new elements

 
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

gst_rtsp_stream_leave_bin ()

+
gboolean
+gst_rtsp_stream_leave_bin (GstRTSPStream *stream,
+                           GstBin *bin,
+                           GstElement *rtpbin);
+

Remove the elements of stream + from bin +.

+

Return: TRUE on success.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

stream

a GstRTSPStream

 

bin

a GstBin.

[transfer none]

rtpbin

a rtpbin GstElement.

[transfer none]
+
+
+
+
+

gst_rtsp_stream_get_server_port ()

+
void
+gst_rtsp_stream_get_server_port (GstRTSPStream *stream,
+                                 GstRTSPRange *server_port,
+                                 GSocketFamily family);
+

Fill server_port + with the port pair used by the server. This function can +only be called when stream + has been joined.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

stream

a GstRTSPStream

 

server_port

result server port.

[out]

family

the port family to get

 
+
+
+
+
+

gst_rtsp_stream_get_multicast_address ()

+
GstRTSPAddress *
+gst_rtsp_stream_get_multicast_address (GstRTSPStream *stream,
+                                       GSocketFamily family);
+

Get the multicast address of stream + for family +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

family

the GSocketFamily

 
+
+
+

Returns

+

the GstRTSPAddress of stream +or NULL when no address could be allocated. gst_rtsp_address_free() +after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_rtsp_stream_get_rtpsession ()

+
GObject *
+gst_rtsp_stream_get_rtpsession (GstRTSPStream *stream);
+

Get the RTP session of this stream.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+

Returns

+

The RTP session of this stream. Unref after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_stream_get_ssrc ()

+
void
+gst_rtsp_stream_get_ssrc (GstRTSPStream *stream,
+                          guint *ssrc);
+

Get the SSRC used by the RTP session of this stream. This function can only +be called when stream + has been joined.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

ssrc

result ssrc.

[out]
+
+
+
+
+

gst_rtsp_stream_get_rtpinfo ()

+
gboolean
+gst_rtsp_stream_get_rtpinfo (GstRTSPStream *stream,
+                             guint *rtptime,
+                             guint *seq,
+                             guint *clock_rate,
+                             GstClockTime *running_time);
+

Retrieve the current rtptime, seq and running-time. This is used to +construct a RTPInfo reply header.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

stream

a GstRTSPStream

 

rtptime

result RTP timestamp.

[allow-none]

seq

result RTP seqnum.

[allow-none]

clock_rate

the clock rate.

[allow-none]

running_time

result running-time.

[allow-none]
+
+
+

Returns

+

TRUE when rtptime, seq and running-time could be determined.

+

+
+
+
+
+

gst_rtsp_stream_get_caps ()

+
GstCaps *
+gst_rtsp_stream_get_caps (GstRTSPStream *stream);
+

Retrieve the current caps of stream +.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+

Returns

+

the GstCaps of stream +. use gst_caps_unref() +after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_stream_get_pt ()

+
guint
+gst_rtsp_stream_get_pt (GstRTSPStream *stream);
+

Get the stream payload type.

+

Return: the stream payload type.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+
+
+

gst_rtsp_stream_recv_rtcp ()

+
GstFlowReturn
+gst_rtsp_stream_recv_rtcp (GstRTSPStream *stream,
+                           GstBuffer *buffer);
+

Handle an RTCP buffer for the stream. This method is usually called when a +message has been received from a client using the TCP transport.

+

This function takes ownership of buffer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

buffer

a GstBuffer.

[transfer full]
+
+
+

Returns

+

a GstFlowReturn.

+

+
+
+
+
+

gst_rtsp_stream_recv_rtp ()

+
GstFlowReturn
+gst_rtsp_stream_recv_rtp (GstRTSPStream *stream,
+                          GstBuffer *buffer);
+

Handle an RTP buffer for the stream. This method is usually called when a +message has been received from a client using the TCP transport.

+

This function takes ownership of buffer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

buffer

a GstBuffer.

[transfer full]
+
+
+

Returns

+

a GstFlowReturn.

+

+
+
+
+
+

gst_rtsp_stream_add_transport ()

+
gboolean
+gst_rtsp_stream_add_transport (GstRTSPStream *stream,
+                               GstRTSPStreamTransport *trans);
+

Add the transport in trans + to stream +. The media of stream + will +then also be send to the values configured in trans +.

+

stream + must be joined to a bin.

+

trans + must contain a valid GstRTSPTransport.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

trans

a GstRTSPStreamTransport.

[transfer none]
+
+
+

Returns

+

TRUE if trans +was added

+

+
+
+
+
+

gst_rtsp_stream_remove_transport ()

+
gboolean
+gst_rtsp_stream_remove_transport (GstRTSPStream *stream,
+                                  GstRTSPStreamTransport *trans);
+

Remove the transport in trans + from stream +. The media of stream + will +not be sent to the values configured in trans +.

+

stream + must be joined to a bin.

+

trans + must contain a valid GstRTSPTransport.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

trans

a GstRTSPStreamTransport.

[transfer none]
+
+
+

Returns

+

TRUE if trans +was removed

+

+
+
+
+
+

gst_rtsp_stream_get_rtp_socket ()

+
GSocket *
+gst_rtsp_stream_get_rtp_socket (GstRTSPStream *stream,
+                                GSocketFamily family);
+

Get the RTP socket from stream + for a family +.

+

stream + must be joined to a bin.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

family

the socket family

 
+
+
+

Returns

+

the RTP socket or NULL if no +socket could be allocated for family +. Unref after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_rtsp_stream_get_rtcp_socket ()

+
GSocket *
+gst_rtsp_stream_get_rtcp_socket (GstRTSPStream *stream,
+                                 GSocketFamily family);
+

Get the RTCP socket from stream + for a family +.

+

stream + must be joined to a bin.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

family

the socket family

 
+
+
+

Returns

+

the RTCP socket or NULL if no +socket could be allocated for family +. Unref after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_rtsp_stream_set_blocked ()

+
gboolean
+gst_rtsp_stream_set_blocked (GstRTSPStream *stream,
+                             gboolean blocked);
+

Blocks or unblocks the dataflow on stream +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

blocked

boolean indicating we should block or unblock

 
+
+
+

Returns

+

TRUE on success

+

+
+
+
+
+

gst_rtsp_stream_is_blocking ()

+
gboolean
+gst_rtsp_stream_is_blocking (GstRTSPStream *stream);
+

Check if stream + is blocking on a GstBuffer.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstRTSPStream

 
+
+
+

Returns

+

TRUE if stream +is blocking

+

+
+
+
+
+

gst_rtsp_stream_update_crypto ()

+
gboolean
+gst_rtsp_stream_update_crypto (GstRTSPStream *stream,
+                               guint ssrc,
+                               GstCaps *crypto);
+

Update the new crypto information for ssrc + in stream +. If information +for ssrc + did not exist, it will be added. If information +for ssrc + existed, it will be replaced. If crypto + is NULL, it will +be removed from stream +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

stream

a GstRTSPStream

 

ssrc

the SSRC

 

crypto

a GstCaps with crypto info.

[transfer none][allow-none]
+
+
+

Returns

+

TRUE if crypto +could be updated

+

+
+
+
+
+

GstRTSPStreamTransportFilterFunc ()

+
GstRTSPFilterResult
+(*GstRTSPStreamTransportFilterFunc) (GstRTSPStream *stream,
+                                     GstRTSPStreamTransport *trans,
+                                     gpointer user_data);
+

This function will be called by the gst_rtsp_stream_transport_filter(). An +implementation should return a value of GstRTSPFilterResult.

+

When this function returns GST_RTSP_FILTER_REMOVE, trans + will be removed +from stream +.

+

A return value of GST_RTSP_FILTER_KEEP will leave trans + untouched in +stream +.

+

A value of GST_RTSP_FILTER_REF will add trans + to the result GList of +gst_rtsp_stream_transport_filter().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

stream

a GstRTSPStream object

 

trans

a GstRTSPStreamTransport in stream +

 

user_data

user data that has been given to gst_rtsp_stream_transport_filter()

 
+
+
+

Returns

+

a GstRTSPFilterResult.

+

+
+
+
+
+

gst_rtsp_stream_transport_filter ()

+
GList *
+gst_rtsp_stream_transport_filter (GstRTSPStream *stream,
+                                  GstRTSPStreamTransportFilterFunc func,
+                                  gpointer user_data);
+

Call func + for each transport managed by stream +. The result value of func + +determines what happens to the transport. func + will be called with stream + +locked so no further actions on stream + can be performed from func +.

+

If func + returns GST_RTSP_FILTER_REMOVE, the transport will be removed from +stream +.

+

If func + returns GST_RTSP_FILTER_KEEP, the transport will remain in stream +.

+

If func + returns GST_RTSP_FILTER_REF, the transport will remain in stream + but +will also be added with an additional ref to the result GList of this +function..

+

When func + is NULL, GST_RTSP_FILTER_REF will be assumed for each transport.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

stream

a GstRTSPStream

 

func

a callback.

[scope call][allow-none]

user_data

user data passed to func +.

[closure]
+
+
+

Returns

+

a GList with all +transports for which func +returned GST_RTSP_FILTER_REF. After usage, each +element in the GList should be unreffed before the list is freed.

+

[element-type GstRTSPStreamTransport][transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstRTSPStream

+
struct GstRTSPStream;
+

The definition of a media stream.

+
+
+
+

GstRTSPStreamClass

+
typedef struct _GstRTSPStreamClass GstRTSPStreamClass;
+
+
+
+

See Also

+

GstRTSPMedia

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/annotation-glossary.html b/docs/libs/html/annotation-glossary.html new file mode 100644 index 0000000..4326d28 --- /dev/null +++ b/docs/libs/html/annotation-glossary.html @@ -0,0 +1,70 @@ + + + + +GStreamer RTSP Server Reference Manual: Annotation Glossary + + + + + + + + + + + + + + + +
+

+Annotation Glossary

+

A

+
allow-none
+

NULL is OK, both for passing and for returning.

+

C

+
closure
+

This parameter is a 'user_data', for callbacks; many bindings can pass NULL here.

+

E

+
element-type
+

Generics and defining elements of containers and arrays.

+

N

+
nullable
+

NULL may be passed as the value in, out, in-out; or as a return value.

+

O

+
out
+

Parameter for returning results. Default is transfer full.

+

S

+
scope call
+

The callback is valid only during the call to the method.

+
scope notified
+

The callback is valid until the GDestroyNotify argument is called.

+

T

+
transfer floating
+

Alias for transfer none, used for objects with floating refs.

+
transfer full
+

Free data after the code is done.

+
transfer none
+

Don't free data after the code is done.

+
type
+

Override the parsed C type with given type.

+
+ + + \ No newline at end of file diff --git a/docs/libs/html/api-index-full.html b/docs/libs/html/api-index-full.html new file mode 100644 index 0000000..671e5d5 --- /dev/null +++ b/docs/libs/html/api-index-full.html @@ -0,0 +1,1470 @@ + + + + +GStreamer RTSP Server Reference Manual: API Index + + + + + + + + + + + + + + + + +
+

+API Index

+

R

+
+GstRTSPAddress, struct in GstRTSPAddressPool +
+
+
+GstRTSPAddressFlags, enum in GstRTSPAddressPool +
+
+
+GstRTSPAddressPool, struct in GstRTSPAddressPool +
+
+
+GstRTSPAddressPoolClass, struct in GstRTSPAddressPool +
+
+
+GstRTSPAddressPoolResult, enum in GstRTSPAddressPool +
+
+
+GstRTSPAuth, struct in GstRTSPAuth +
+
+
+GstRTSPAuthClass, struct in GstRTSPAuth +
+
+
+GstRTSPClient, struct in GstRTSPClient +
+
+
+GstRTSPClient::closed, object signal in GstRTSPClient +
+
+
+GstRTSPClient::describe-request, object signal in GstRTSPClient +
+
+
+GstRTSPClient::get-parameter-request, object signal in GstRTSPClient +
+
+
+GstRTSPClient::handle-response, object signal in GstRTSPClient +
+
+
+GstRTSPClient::new-session, object signal in GstRTSPClient +
+
+
+GstRTSPClient::options-request, object signal in GstRTSPClient +
+
+
+GstRTSPClient::pause-request, object signal in GstRTSPClient +
+
+
+GstRTSPClient::play-request, object signal in GstRTSPClient +
+
+
+GstRTSPClient::send-message, object signal in GstRTSPClient +
+
+
+GstRTSPClient::set-parameter-request, object signal in GstRTSPClient +
+
+
+GstRTSPClient::setup-request, object signal in GstRTSPClient +
+
+
+GstRTSPClient::teardown-request, object signal in GstRTSPClient +
+
+
+GstRTSPClient:drop-backlog, object property in GstRTSPClient +
+
+
+GstRTSPClient:mount-points, object property in GstRTSPClient +
+
+
+GstRTSPClient:session-pool, object property in GstRTSPClient +
+
+
+GstRTSPClientClass, struct in GstRTSPClient +
+
+
+GstRTSPClientSendFunc, user_function in GstRTSPClient +
+
+
+GstRTSPClientSessionFilterFunc, user_function in GstRTSPClient +
+
+
+GstRTSPContext, struct in GstRTSPContext +
+
+
+GstRTSPFilterResult, enum in GstRTSPSession +
+
+
+GstRTSPKeepAliveFunc, user_function in GstRTSPStreamTransport +
+
+
+GstRTSPMedia, struct in GstRTSPMedia +
+
+
+GstRTSPMedia::new-state, object signal in GstRTSPMedia +
+
+
+GstRTSPMedia::new-stream, object signal in GstRTSPMedia +
+
+
+GstRTSPMedia::prepared, object signal in GstRTSPMedia +
+
+
+GstRTSPMedia::removed-stream, object signal in GstRTSPMedia +
+
+
+GstRTSPMedia::target-state, object signal in GstRTSPMedia +
+
+
+GstRTSPMedia::unprepared, object signal in GstRTSPMedia +
+
+
+GstRTSPMedia:buffer-size, object property in GstRTSPMedia +
+
+
+GstRTSPMedia:element, object property in GstRTSPMedia +
+
+
+GstRTSPMedia:eos-shutdown, object property in GstRTSPMedia +
+
+
+GstRTSPMedia:profiles, object property in GstRTSPMedia +
+
+
+GstRTSPMedia:protocols, object property in GstRTSPMedia +
+
+
+GstRTSPMedia:reusable, object property in GstRTSPMedia +
+
+
+GstRTSPMedia:shared, object property in GstRTSPMedia +
+
+
+GstRTSPMedia:suspend-mode, object property in GstRTSPMedia +
+
+
+GstRTSPMedia:time-provider, object property in GstRTSPMedia +
+
+
+GstRTSPMediaClass, struct in GstRTSPMedia +
+
+
+GstRTSPMediaFactory, struct in GstRTSPMediaFactory +
+
+
+GstRTSPMediaFactory::media-configure, object signal in GstRTSPMediaFactory +
+
+
+GstRTSPMediaFactory::media-constructed, object signal in GstRTSPMediaFactory +
+
+
+GstRTSPMediaFactory:buffer-size, object property in GstRTSPMediaFactory +
+
+
+GstRTSPMediaFactory:eos-shutdown, object property in GstRTSPMediaFactory +
+
+
+GstRTSPMediaFactory:launch, object property in GstRTSPMediaFactory +
+
+
+GstRTSPMediaFactory:profiles, object property in GstRTSPMediaFactory +
+
+
+GstRTSPMediaFactory:protocols, object property in GstRTSPMediaFactory +
+
+
+GstRTSPMediaFactory:shared, object property in GstRTSPMediaFactory +
+
+
+GstRTSPMediaFactory:suspend-mode, object property in GstRTSPMediaFactory +
+
+
+GstRTSPMediaFactoryClass, struct in GstRTSPMediaFactory +
+
+
+GstRTSPMediaFactoryURI, struct in GstRTSPMediaFactoryURI +
+
+
+GstRTSPMediaFactoryURIClass, struct in GstRTSPMediaFactoryURI +
+
+
+GstRTSPMediaStatus, enum in GstRTSPMedia +
+
+
+GstRTSPMountPoints, struct in GstRTSPMountPoints +
+
+
+GstRTSPMountPointsClass, struct in GstRTSPMountPoints +
+
+
+GstRTSPPermissions, struct in GstRTSPPermissions +
+
+
+GstRTSPSendFunc, user_function in GstRTSPStreamTransport +
+
+
+GstRTSPServer, struct in GstRTSPServer +
+
+
+GstRTSPServer::client-connected, object signal in GstRTSPServer +
+
+
+GstRTSPServer:address, object property in GstRTSPServer +
+
+
+GstRTSPServer:backlog, object property in GstRTSPServer +
+
+
+GstRTSPServer:bound-port, object property in GstRTSPServer +
+
+
+GstRTSPServer:mount-points, object property in GstRTSPServer +
+
+
+GstRTSPServer:service, object property in GstRTSPServer +
+
+
+GstRTSPServer:session-pool, object property in GstRTSPServer +
+
+
+GstRTSPServerClass, struct in GstRTSPServer +
+
+
+GstRTSPServerClientFilterFunc, user_function in GstRTSPServer +
+
+
+GstRTSPSession, struct in GstRTSPSession +
+
+
+GstRTSPSession:sessionid, object property in GstRTSPSession +
+
+
+GstRTSPSession:timeout, object property in GstRTSPSession +
+
+
+GstRTSPSession:timeout-always-visible, object property in GstRTSPSession +
+
+
+GstRTSPSessionClass, struct in GstRTSPSession +
+
+
+GstRTSPSessionFilterFunc, user_function in GstRTSPSession +
+
+
+GstRTSPSessionMedia, struct in GstRTSPSessionMedia +
+
+
+GstRTSPSessionMediaClass, struct in GstRTSPSessionMedia +
+
+
+GstRTSPSessionPool, struct in GstRTSPSessionPool +
+
+
+GstRTSPSessionPool::session-removed, object signal in GstRTSPSessionPool +
+
+
+GstRTSPSessionPool:max-sessions, object property in GstRTSPSessionPool +
+
+
+GstRTSPSessionPoolClass, struct in GstRTSPSessionPool +
+
+
+GstRTSPSessionPoolFilterFunc, user_function in GstRTSPSessionPool +
+
+
+GstRTSPSessionPoolFunc, user_function in GstRTSPSessionPool +
+
+
+GstRTSPStream, struct in GstRTSPStream +
+
+
+GstRTSPStreamClass, struct in GstRTSPStream +
+
+
+GstRTSPStreamTransport, struct in GstRTSPStreamTransport +
+
+
+GstRTSPStreamTransportClass, struct in GstRTSPStreamTransport +
+
+
+GstRTSPStreamTransportFilterFunc, user_function in GstRTSPStream +
+
+
+GstRTSPSuspendMode, enum in GstRTSPMedia +
+
+
+GstRTSPThread, struct in GstRTSPThreadPool +
+
+
+GstRTSPThreadPool, struct in GstRTSPThreadPool +
+
+
+GstRTSPThreadPoolClass, struct in GstRTSPThreadPool +
+
+
+GstRTSPThreadType, enum in GstRTSPThreadPool +
+
+
+GstRTSPToken, struct in GstRTSPToken +
+
+
+gst_rtsp_address_copy, function in GstRTSPAddressPool +
+
+
+gst_rtsp_address_free, function in GstRTSPAddressPool +
+
+
+gst_rtsp_address_pool_acquire_address, function in GstRTSPAddressPool +
+
+
+gst_rtsp_address_pool_add_range, function in GstRTSPAddressPool +
+
+
+GST_RTSP_ADDRESS_POOL_ANY_IPV4, macro in GstRTSPAddressPool +
+
+
+GST_RTSP_ADDRESS_POOL_ANY_IPV6, macro in GstRTSPAddressPool +
+
+
+gst_rtsp_address_pool_clear, function in GstRTSPAddressPool +
+
+
+gst_rtsp_address_pool_dump, function in GstRTSPAddressPool +
+
+
+gst_rtsp_address_pool_has_unicast_addresses, function in GstRTSPAddressPool +
+
+
+gst_rtsp_address_pool_new, function in GstRTSPAddressPool +
+
+
+gst_rtsp_address_pool_reserve_address, function in GstRTSPAddressPool +
+
+
+gst_rtsp_auth_add_basic, function in GstRTSPAuth +
+
+
+gst_rtsp_auth_check, function in GstRTSPAuth +
+
+
+GST_RTSP_AUTH_CHECK_CONNECT, macro in GstRTSPAuth +
+
+
+GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS, macro in GstRTSPAuth +
+
+
+GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT, macro in GstRTSPAuth +
+
+
+GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS, macro in GstRTSPAuth +
+
+
+GST_RTSP_AUTH_CHECK_URL, macro in GstRTSPAuth +
+
+
+gst_rtsp_auth_get_default_token, function in GstRTSPAuth +
+
+
+gst_rtsp_auth_get_tls_certificate, function in GstRTSPAuth +
+
+
+gst_rtsp_auth_make_basic, function in GstRTSPAuth +
+
+
+gst_rtsp_auth_new, function in GstRTSPAuth +
+
+
+gst_rtsp_auth_remove_basic, function in GstRTSPAuth +
+
+
+gst_rtsp_auth_set_default_token, function in GstRTSPAuth +
+
+
+gst_rtsp_auth_set_tls_certificate, function in GstRTSPAuth +
+
+
+gst_rtsp_client_attach, function in GstRTSPClient +
+
+
+gst_rtsp_client_close, function in GstRTSPClient +
+
+
+gst_rtsp_client_get_auth, function in GstRTSPClient +
+
+
+gst_rtsp_client_get_connection, function in GstRTSPClient +
+
+
+gst_rtsp_client_get_mount_points, function in GstRTSPClient +
+
+
+gst_rtsp_client_get_session_pool, function in GstRTSPClient +
+
+
+gst_rtsp_client_get_thread_pool, function in GstRTSPClient +
+
+
+gst_rtsp_client_handle_message, function in GstRTSPClient +
+
+
+gst_rtsp_client_new, function in GstRTSPClient +
+
+
+gst_rtsp_client_send_message, function in GstRTSPClient +
+
+
+gst_rtsp_client_session_filter, function in GstRTSPClient +
+
+
+gst_rtsp_client_set_auth, function in GstRTSPClient +
+
+
+gst_rtsp_client_set_connection, function in GstRTSPClient +
+
+
+gst_rtsp_client_set_mount_points, function in GstRTSPClient +
+
+
+gst_rtsp_client_set_send_func, function in GstRTSPClient +
+
+
+gst_rtsp_client_set_session_pool, function in GstRTSPClient +
+
+
+gst_rtsp_client_set_thread_pool, function in GstRTSPClient +
+
+
+gst_rtsp_context_get_current, function in GstRTSPContext +
+
+
+gst_rtsp_context_pop_current, function in GstRTSPContext +
+
+
+gst_rtsp_context_push_current, function in GstRTSPContext +
+
+
+gst_rtsp_media_collect_streams, function in GstRTSPMedia +
+
+
+gst_rtsp_media_create_stream, function in GstRTSPMedia +
+
+
+gst_rtsp_media_factory_add_role, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_construct, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_create_element, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_get_address_pool, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_get_buffer_size, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_get_launch, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_get_permissions, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_get_profiles, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_get_protocols, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_get_suspend_mode, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_is_eos_shutdown, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_is_shared, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_new, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_set_address_pool, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_set_buffer_size, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_set_eos_shutdown, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_set_launch, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_set_permissions, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_set_profiles, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_set_protocols, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_set_shared, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_set_suspend_mode, function in GstRTSPMediaFactory +
+
+
+gst_rtsp_media_factory_uri_get_uri, function in GstRTSPMediaFactoryURI +
+
+
+gst_rtsp_media_factory_uri_new, function in GstRTSPMediaFactoryURI +
+
+
+gst_rtsp_media_factory_uri_set_uri, function in GstRTSPMediaFactoryURI +
+
+
+gst_rtsp_media_find_stream, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_address_pool, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_base_time, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_buffer_size, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_clock, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_element, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_permissions, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_profiles, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_protocols, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_range_string, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_status, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_stream, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_suspend_mode, function in GstRTSPMedia +
+
+
+gst_rtsp_media_get_time_provider, function in GstRTSPMedia +
+
+
+gst_rtsp_media_is_eos_shutdown, function in GstRTSPMedia +
+
+
+gst_rtsp_media_is_reusable, function in GstRTSPMedia +
+
+
+gst_rtsp_media_is_shared, function in GstRTSPMedia +
+
+
+gst_rtsp_media_is_time_provider, function in GstRTSPMedia +
+
+
+gst_rtsp_media_new, function in GstRTSPMedia +
+
+
+gst_rtsp_media_n_streams, function in GstRTSPMedia +
+
+
+gst_rtsp_media_prepare, function in GstRTSPMedia +
+
+
+gst_rtsp_media_seek, function in GstRTSPMedia +
+
+
+gst_rtsp_media_setup_sdp, function in GstRTSPMedia +
+
+
+gst_rtsp_media_set_address_pool, function in GstRTSPMedia +
+
+
+gst_rtsp_media_set_buffer_size, function in GstRTSPMedia +
+
+
+gst_rtsp_media_set_eos_shutdown, function in GstRTSPMedia +
+
+
+gst_rtsp_media_set_permissions, function in GstRTSPMedia +
+
+
+gst_rtsp_media_set_pipeline_state, function in GstRTSPMedia +
+
+
+gst_rtsp_media_set_profiles, function in GstRTSPMedia +
+
+
+gst_rtsp_media_set_protocols, function in GstRTSPMedia +
+
+
+gst_rtsp_media_set_reusable, function in GstRTSPMedia +
+
+
+gst_rtsp_media_set_shared, function in GstRTSPMedia +
+
+
+gst_rtsp_media_set_state, function in GstRTSPMedia +
+
+
+gst_rtsp_media_set_suspend_mode, function in GstRTSPMedia +
+
+
+gst_rtsp_media_suspend, function in GstRTSPMedia +
+
+
+gst_rtsp_media_take_pipeline, function in GstRTSPMedia +
+
+
+gst_rtsp_media_unprepare, function in GstRTSPMedia +
+
+
+gst_rtsp_media_unsuspend, function in GstRTSPMedia +
+
+
+gst_rtsp_media_use_time_provider, function in GstRTSPMedia +
+
+
+gst_rtsp_mount_points_add_factory, function in GstRTSPMountPoints +
+
+
+gst_rtsp_mount_points_make_path, function in GstRTSPMountPoints +
+
+
+gst_rtsp_mount_points_match, function in GstRTSPMountPoints +
+
+
+gst_rtsp_mount_points_new, function in GstRTSPMountPoints +
+
+
+gst_rtsp_mount_points_remove_factory, function in GstRTSPMountPoints +
+
+
+gst_rtsp_params_get, function in GstRTSPParams +
+
+
+gst_rtsp_params_set, function in GstRTSPParams +
+
+
+gst_rtsp_permissions_add_role, function in GstRTSPPermissions +
+
+
+gst_rtsp_permissions_add_role_valist, function in GstRTSPPermissions +
+
+
+gst_rtsp_permissions_get_role, function in GstRTSPPermissions +
+
+
+gst_rtsp_permissions_is_allowed, function in GstRTSPPermissions +
+
+
+gst_rtsp_permissions_new, function in GstRTSPPermissions +
+
+
+gst_rtsp_permissions_ref, function in GstRTSPPermissions +
+
+
+gst_rtsp_permissions_remove_role, function in GstRTSPPermissions +
+
+
+gst_rtsp_permissions_unref, function in GstRTSPPermissions +
+
+
+GST_RTSP_PERM_MEDIA_FACTORY_ACCESS, macro in GstRTSPAuth +
+
+
+GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT, macro in GstRTSPAuth +
+
+
+gst_rtsp_sdp_from_media, function in GstRTSPSdp +
+
+
+gst_rtsp_server_attach, function in GstRTSPServer +
+
+
+gst_rtsp_server_client_filter, function in GstRTSPServer +
+
+
+gst_rtsp_server_create_socket, function in GstRTSPServer +
+
+
+gst_rtsp_server_create_source, function in GstRTSPServer +
+
+
+gst_rtsp_server_get_address, function in GstRTSPServer +
+
+
+gst_rtsp_server_get_auth, function in GstRTSPServer +
+
+
+gst_rtsp_server_get_backlog, function in GstRTSPServer +
+
+
+gst_rtsp_server_get_bound_port, function in GstRTSPServer +
+
+
+gst_rtsp_server_get_mount_points, function in GstRTSPServer +
+
+
+gst_rtsp_server_get_service, function in GstRTSPServer +
+
+
+gst_rtsp_server_get_session_pool, function in GstRTSPServer +
+
+
+gst_rtsp_server_get_thread_pool, function in GstRTSPServer +
+
+
+gst_rtsp_server_io_func, function in GstRTSPServer +
+
+
+gst_rtsp_server_new, function in GstRTSPServer +
+
+
+gst_rtsp_server_set_address, function in GstRTSPServer +
+
+
+gst_rtsp_server_set_auth, function in GstRTSPServer +
+
+
+gst_rtsp_server_set_backlog, function in GstRTSPServer +
+
+
+gst_rtsp_server_set_mount_points, function in GstRTSPServer +
+
+
+gst_rtsp_server_set_service, function in GstRTSPServer +
+
+
+gst_rtsp_server_set_session_pool, function in GstRTSPServer +
+
+
+gst_rtsp_server_set_thread_pool, function in GstRTSPServer +
+
+
+gst_rtsp_server_transfer_connection, function in GstRTSPServer +
+
+
+gst_rtsp_session_allow_expire, function in GstRTSPSession +
+
+
+gst_rtsp_session_filter, function in GstRTSPSession +
+
+
+gst_rtsp_session_get_header, function in GstRTSPSession +
+
+
+gst_rtsp_session_get_media, function in GstRTSPSession +
+
+
+gst_rtsp_session_get_sessionid, function in GstRTSPSession +
+
+
+gst_rtsp_session_get_timeout, function in GstRTSPSession +
+
+
+gst_rtsp_session_is_expired, function in GstRTSPSession +
+
+
+gst_rtsp_session_manage_media, function in GstRTSPSession +
+
+
+gst_rtsp_session_media_alloc_channels, function in GstRTSPSessionMedia +
+
+
+gst_rtsp_session_media_get_base_time, function in GstRTSPSessionMedia +
+
+
+gst_rtsp_session_media_get_media, function in GstRTSPSessionMedia +
+
+
+gst_rtsp_session_media_get_rtpinfo, function in GstRTSPSessionMedia +
+
+
+gst_rtsp_session_media_get_rtsp_state, function in GstRTSPSessionMedia +
+
+
+gst_rtsp_session_media_get_transport, function in GstRTSPSessionMedia +
+
+
+gst_rtsp_session_media_matches, function in GstRTSPSessionMedia +
+
+
+gst_rtsp_session_media_new, function in GstRTSPSessionMedia +
+
+
+gst_rtsp_session_media_set_rtsp_state, function in GstRTSPSessionMedia +
+
+
+gst_rtsp_session_media_set_state, function in GstRTSPSessionMedia +
+
+
+gst_rtsp_session_media_set_transport, function in GstRTSPSessionMedia +
+
+
+gst_rtsp_session_new, function in GstRTSPSession +
+
+
+gst_rtsp_session_next_timeout, function in GstRTSPSession +
+
+
+gst_rtsp_session_pool_cleanup, function in GstRTSPSessionPool +
+
+
+gst_rtsp_session_pool_create, function in GstRTSPSessionPool +
+
+
+gst_rtsp_session_pool_create_watch, function in GstRTSPSessionPool +
+
+
+gst_rtsp_session_pool_filter, function in GstRTSPSessionPool +
+
+
+gst_rtsp_session_pool_find, function in GstRTSPSessionPool +
+
+
+gst_rtsp_session_pool_get_max_sessions, function in GstRTSPSessionPool +
+
+
+gst_rtsp_session_pool_get_n_sessions, function in GstRTSPSessionPool +
+
+
+gst_rtsp_session_pool_new, function in GstRTSPSessionPool +
+
+
+gst_rtsp_session_pool_remove, function in GstRTSPSessionPool +
+
+
+gst_rtsp_session_pool_set_max_sessions, function in GstRTSPSessionPool +
+
+
+gst_rtsp_session_prevent_expire, function in GstRTSPSession +
+
+
+gst_rtsp_session_release_media, function in GstRTSPSession +
+
+
+gst_rtsp_session_set_timeout, function in GstRTSPSession +
+
+
+gst_rtsp_session_touch, function in GstRTSPSession +
+
+
+gst_rtsp_stream_add_transport, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_address_pool, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_caps, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_control, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_dscp_qos, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_index, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_mtu, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_multicast_address, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_profiles, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_protocols, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_pt, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_rtcp_socket, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_rtpinfo, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_rtpsession, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_rtp_socket, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_server_port, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_srcpad, function in GstRTSPStream +
+
+
+gst_rtsp_stream_get_ssrc, function in GstRTSPStream +
+
+
+gst_rtsp_stream_has_control, function in GstRTSPStream +
+
+
+gst_rtsp_stream_is_blocking, function in GstRTSPStream +
+
+
+gst_rtsp_stream_is_transport_supported, function in GstRTSPStream +
+
+
+gst_rtsp_stream_join_bin, function in GstRTSPStream +
+
+
+gst_rtsp_stream_leave_bin, function in GstRTSPStream +
+
+
+gst_rtsp_stream_new, function in GstRTSPStream +
+
+
+gst_rtsp_stream_recv_rtcp, function in GstRTSPStream +
+
+
+gst_rtsp_stream_recv_rtp, function in GstRTSPStream +
+
+
+gst_rtsp_stream_remove_transport, function in GstRTSPStream +
+
+
+gst_rtsp_stream_reserve_address, function in GstRTSPStream +
+
+
+gst_rtsp_stream_set_address_pool, function in GstRTSPStream +
+
+
+gst_rtsp_stream_set_blocked, function in GstRTSPStream +
+
+
+gst_rtsp_stream_set_control, function in GstRTSPStream +
+
+
+gst_rtsp_stream_set_dscp_qos, function in GstRTSPStream +
+
+
+gst_rtsp_stream_set_mtu, function in GstRTSPStream +
+
+
+gst_rtsp_stream_set_profiles, function in GstRTSPStream +
+
+
+gst_rtsp_stream_set_protocols, function in GstRTSPStream +
+
+
+gst_rtsp_stream_transport_filter, function in GstRTSPStream +
+
+
+gst_rtsp_stream_transport_get_rtpinfo, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_get_stream, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_get_transport, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_get_url, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_is_timed_out, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_keep_alive, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_new, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_send_rtcp, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_send_rtp, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_set_active, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_set_callbacks, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_set_keepalive, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_set_timed_out, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_set_transport, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_transport_set_url, function in GstRTSPStreamTransport +
+
+
+gst_rtsp_stream_update_crypto, function in GstRTSPStream +
+
+
+gst_rtsp_thread_new, function in GstRTSPThreadPool +
+
+
+gst_rtsp_thread_pool_cleanup, function in GstRTSPThreadPool +
+
+
+gst_rtsp_thread_pool_get_max_threads, function in GstRTSPThreadPool +
+
+
+gst_rtsp_thread_pool_get_thread, function in GstRTSPThreadPool +
+
+
+gst_rtsp_thread_pool_new, function in GstRTSPThreadPool +
+
+
+gst_rtsp_thread_pool_set_max_threads, function in GstRTSPThreadPool +
+
+
+gst_rtsp_thread_ref, function in GstRTSPThreadPool +
+
+
+gst_rtsp_thread_reuse, function in GstRTSPThreadPool +
+
+
+gst_rtsp_thread_stop, function in GstRTSPThreadPool +
+
+
+gst_rtsp_thread_unref, function in GstRTSPThreadPool +
+
+
+gst_rtsp_token_get_string, function in GstRTSPToken +
+
+
+gst_rtsp_token_get_structure, function in GstRTSPToken +
+
+
+gst_rtsp_token_is_allowed, function in GstRTSPToken +
+
+
+GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, macro in GstRTSPAuth +
+
+
+gst_rtsp_token_new, function in GstRTSPToken +
+
+
+gst_rtsp_token_new_empty, function in GstRTSPToken +
+
+
+gst_rtsp_token_new_valist, function in GstRTSPToken +
+
+
+gst_rtsp_token_ref, function in GstRTSPToken +
+
+
+GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS, macro in GstRTSPAuth +
+
+
+gst_rtsp_token_unref, function in GstRTSPToken +
+
+
+gst_rtsp_token_writable_structure, function in GstRTSPToken +
+
+

S

+
+GstSDPInfo, struct in GstRTSPSdp +
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/ch01.html b/docs/libs/html/ch01.html new file mode 100644 index 0000000..0173744 --- /dev/null +++ b/docs/libs/html/ch01.html @@ -0,0 +1,88 @@ + + + + +GStreamer RTSP Server Reference Manual: + + + + + + + + + + + + + + + + +
+
+
+
+GstRTSPServer — The main server object +
+
+GstRTSPClient — A client connection state +
+
+GstRTSPContext — A client request context +
+
+GstRTSPMountPoints — Map a path to media +
+
+GstRTSPMediaFactory — A factory for media pipelines +
+
+GstRTSPMediaFactoryURI — A factory for URI sources +
+
+GstRTSPMedia — The media pipeline +
+
+GstRTSPStream — A media stream +
+
+GstRTSPSessionPool — An object for managing sessions +
+
+GstRTSPSession — An object to manage media +
+
+GstRTSPSessionMedia — Media managed in a session +
+
+GstRTSPStreamTransport — A media stream transport configuration +
+
+GstRTSPSdp — Make SDP messages +
+
+GstRTSPAddressPool — A pool of network addresses +
+
+GstRTSPThreadPool — A pool of threads +
+
+GstRTSPAuth — Authentication and authorization +
+
+GstRTSPToken — Roles and permissions for a client +
+
+GstRTSPPermissions — Roles and associated permissions +
+
+GstRTSPParams — Param get and set implementation +
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gst-rtsp-server-1.0.devhelp2 b/docs/libs/html/gst-rtsp-server-1.0.devhelp2 new file mode 100644 index 0000000..3569b7c --- /dev/null +++ b/docs/libs/html/gst-rtsp-server-1.0.devhelp2 @@ -0,0 +1,391 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/libs/html/gst-rtsp-server-GstRTSPAddressPool.html b/docs/libs/html/gst-rtsp-server-GstRTSPAddressPool.html new file mode 100644 index 0000000..aec2ed1 --- /dev/null +++ b/docs/libs/html/gst-rtsp-server-GstRTSPAddressPool.html @@ -0,0 +1,734 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPAddressPool + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPAddressPool

+

GstRTSPAddressPool — A pool of network addresses

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPAddress * + +gst_rtsp_address_copy () +
+void + +gst_rtsp_address_free () +
+GstRTSPAddressPool * + +gst_rtsp_address_pool_new () +
+void + +gst_rtsp_address_pool_clear () +
+void + +gst_rtsp_address_pool_dump () +
+gboolean + +gst_rtsp_address_pool_add_range () +
+gboolean + +gst_rtsp_address_pool_has_unicast_addresses () +
+GstRTSPAddress * + +gst_rtsp_address_pool_acquire_address () +
+GstRTSPAddressPoolResult + +gst_rtsp_address_pool_reserve_address () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#defineGST_RTSP_ADDRESS_POOL_ANY_IPV4
#defineGST_RTSP_ADDRESS_POOL_ANY_IPV6
structGstRTSPAddress
enumGstRTSPAddressFlags
structGstRTSPAddressPool
structGstRTSPAddressPoolClass
enumGstRTSPAddressPoolResult
+
+
+

Description

+

The GstRTSPAddressPool is an object that maintains a collection of network +addresses. It is used to allocate server ports and server multicast addresses +but also to reserve client provided destination addresses.

+

A range of addresses can be added with gst_rtsp_address_pool_add_range(). +Both multicast and unicast addresses can be added.

+

With gst_rtsp_address_pool_acquire_address() an unused address and port range +can be acquired from the pool. With gst_rtsp_address_pool_reserve_address() a +specific address can be retrieved. Both methods return a boxed +GstRTSPAddress that should be freed with gst_rtsp_address_free() after +usage, which brings the address back into the pool.

+

Last reviewed on 2013-07-16 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_address_copy ()

+
GstRTSPAddress *
+gst_rtsp_address_copy (GstRTSPAddress *addr);
+

Make a copy of addr +.

+
+

Parameters

+
+++++ + + + + + +

addr

a GstRTSPAddress

 
+
+
+

Returns

+

a copy of addr +.

+

+
+
+
+
+

gst_rtsp_address_free ()

+
void
+gst_rtsp_address_free (GstRTSPAddress *addr);
+

Free addr + and releasing it back into the pool when owned by a +pool.

+
+

Parameters

+
+++++ + + + + + +

addr

a GstRTSPAddress

 
+
+
+
+
+

gst_rtsp_address_pool_new ()

+
GstRTSPAddressPool *
+gst_rtsp_address_pool_new (void);
+

Make a new GstRTSPAddressPool.

+
+

Returns

+

a new GstRTSPAddressPool.

+

[transfer full]

+
+
+
+
+

gst_rtsp_address_pool_clear ()

+
void
+gst_rtsp_address_pool_clear (GstRTSPAddressPool *pool);
+

Clear all addresses in pool +. There should be no outstanding +allocations.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstRTSPAddressPool

 
+
+
+
+
+

gst_rtsp_address_pool_dump ()

+
void
+gst_rtsp_address_pool_dump (GstRTSPAddressPool *pool);
+

Dump the free and allocated addresses to stdout.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstRTSPAddressPool

 
+
+
+
+
+

gst_rtsp_address_pool_add_range ()

+
gboolean
+gst_rtsp_address_pool_add_range (GstRTSPAddressPool *pool,
+                                 const gchar *min_address,
+                                 const gchar *max_address,
+                                 guint16 min_port,
+                                 guint16 max_port,
+                                 guint8 ttl);
+

Adds the addresses from min_addess + to max_address + (inclusive) +to pool +. The valid port range for the addresses will be from min_port + to +max_port + inclusive.

+

When ttl + is 0, min_address + and max_address + should be unicast addresses. +min_address + and max_address + can be set to +GST_RTSP_ADDRESS_POOL_ANY_IPV4 or GST_RTSP_ADDRESS_POOL_ANY_IPV6 to bind +to all available IPv4 or IPv6 addresses.

+

When ttl + > 0, min_address + and max_address + should be multicast addresses.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pool

a GstRTSPAddressPool

 

min_address

a minimum address to add

 

max_address

a maximum address to add

 

min_port

the minimum port

 

max_port

the maximum port

 

ttl

a TTL or 0 for unicast addresses

 
+
+
+

Returns

+

TRUE if the addresses could be added.

+

+
+
+
+
+

gst_rtsp_address_pool_has_unicast_addresses ()

+
gboolean
+gst_rtsp_address_pool_has_unicast_addresses
+                               (GstRTSPAddressPool *pool);
+

Used to know if the pool includes any unicast addresses.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstRTSPAddressPool

 
+
+
+

Returns

+

TRUE if the pool includes any unicast addresses, FALSE otherwise

+

+
+
+
+
+

gst_rtsp_address_pool_acquire_address ()

+
GstRTSPAddress *
+gst_rtsp_address_pool_acquire_address (GstRTSPAddressPool *pool,
+                                       GstRTSPAddressFlags flags,
+                                       gint n_ports);
+

Take an address and ports from pool +. flags + can be used to control the +allocation. n_ports + consecutive ports will be allocated of which the first +one can be found in port +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pool

a GstRTSPAddressPool

 

flags

flags

 

n_ports

the amount of ports

 
+
+
+

Returns

+

a GstRTSPAddress that should be freed with +gst_rtsp_address_free after use or NULL when no address could be +acquired.

+

[nullable]

+
+
+
+
+

gst_rtsp_address_pool_reserve_address ()

+
GstRTSPAddressPoolResult
+gst_rtsp_address_pool_reserve_address (GstRTSPAddressPool *pool,
+                                       const gchar *ip_address,
+                                       guint port,
+                                       guint n_ports,
+                                       guint ttl,
+                                       GstRTSPAddress **address);
+

Take a specific address and ports from pool +. n_ports + consecutive +ports will be allocated of which the first one can be found in +port +.

+

If ttl + is 0, address + should be a unicast address. If ttl + > 0, address + +should be a valid multicast address.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pool

a GstRTSPAddressPool

 

ip_address

The IP address to reserve

 

port

The first port to reserve

 

n_ports

The number of ports

 

ttl

The requested ttl

 

address

storage for a GstRTSPAddress.

[out]
+
+
+

Returns

+

GST_RTSP_ADDRESS_POOL_OK if an address was reserved. The address +is returned in address +and should be freed with gst_rtsp_address_free +after use.

+

+
+
+
+
+

Types and Values

+
+

GST_RTSP_ADDRESS_POOL_ANY_IPV4

+
#define GST_RTSP_ADDRESS_POOL_ANY_IPV4  "0.0.0.0"
+
+

Used with gst_rtsp_address_pool_add_range() to bind to all +IPv4 addresses

+
+
+
+

GST_RTSP_ADDRESS_POOL_ANY_IPV6

+
#define GST_RTSP_ADDRESS_POOL_ANY_IPV6  "::"
+
+

Used with gst_rtsp_address_pool_add_range() to bind to all +IPv6 addresses

+
+
+
+

struct GstRTSPAddress

+
struct GstRTSPAddress {
+  GstRTSPAddressPool *pool;
+
+  gchar *address;
+  guint16 port;
+  gint n_ports;
+  guint8 ttl;
+};
+
+

An address

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstRTSPAddressPool *pool;

the GstRTSPAddressPool owner of this address

 

gchar *address;

the address

 

guint16 port;

the port number

 

gint n_ports;

number of ports

 

guint8 ttl;

TTL or 0 for unicast addresses

 
+
+
+
+
+

enum GstRTSPAddressFlags

+

Flags used to control allocation of addresses

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_RTSP_ADDRESS_FLAG_NONE

+

no flags

+
 

GST_RTSP_ADDRESS_FLAG_IPV4

+

an IPv4 address

+
 

GST_RTSP_ADDRESS_FLAG_IPV6

+

and IPv6 address

+
 

GST_RTSP_ADDRESS_FLAG_EVEN_PORT

+

address with an even port

+
 

GST_RTSP_ADDRESS_FLAG_MULTICAST

+

a multicast address

+
 

GST_RTSP_ADDRESS_FLAG_UNICAST

+

a unicast address

+
 
+
+
+
+
+

struct GstRTSPAddressPool

+
struct GstRTSPAddressPool {
+  GObject       parent;
+};
+
+

An address pool, all member are private

+
+

Members

+
+++++ + + + + + +

GObject parent;

the parent GObject

 
+
+
+
+
+

struct GstRTSPAddressPoolClass

+
struct GstRTSPAddressPoolClass {
+  GObjectClass  parent_class;
+};
+
+

Opaque Address pool class.

+
+
+
+

enum GstRTSPAddressPoolResult

+

Result codes from RTSP address pool functions.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_RTSP_ADDRESS_POOL_OK

+

no error

+
 

GST_RTSP_ADDRESS_POOL_EINVAL

+

invalid arguments were provided to a function

+
 

GST_RTSP_ADDRESS_POOL_ERESERVED

+

the addres has already been reserved

+
 

GST_RTSP_ADDRESS_POOL_ERANGE

+

the address is not in the pool

+
 

GST_RTSP_ADDRESS_POOL_ELAST

+

last error

+
 
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/gst-rtsp-server-GstRTSPContext.html b/docs/libs/html/gst-rtsp-server-GstRTSPContext.html new file mode 100644 index 0000000..00c9702 --- /dev/null +++ b/docs/libs/html/gst-rtsp-server-GstRTSPContext.html @@ -0,0 +1,267 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPContext + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPContext

+

GstRTSPContext — A client request context

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + +
+GstRTSPContext * + +gst_rtsp_context_get_current () +
+void + +gst_rtsp_context_push_current () +
+void + +gst_rtsp_context_pop_current () +
+
+
+

Types and Values

+
++++ + + + + +
structGstRTSPContext
+
+
+

Description

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_context_get_current ()

+
GstRTSPContext *
+gst_rtsp_context_get_current (void);
+

Get the current GstRTSPContext. This object is retrieved from the +current thread that is handling the request for a client.

+
+

Returns

+

a GstRTSPContext

+

+
+
+
+
+

gst_rtsp_context_push_current ()

+
void
+gst_rtsp_context_push_current (GstRTSPContext *ctx);
+

Pushes ctx + onto the context stack. The current +context can then be received using gst_rtsp_context_get_current().

+
+

Parameters

+
+++++ + + + + + +

ctx

a #GstRTSPContext

 
+
+
+
+
+

gst_rtsp_context_pop_current ()

+
void
+gst_rtsp_context_pop_current (GstRTSPContext *ctx);
+

Pops ctx + off the context stack (verifying that ctx + +is on the top of the stack).

+
+

Parameters

+
+++++ + + + + + +

ctx

a GstRTSPContext

 
+
+
+
+
+

Types and Values

+
+

struct GstRTSPContext

+
struct GstRTSPContext {
+  GstRTSPServer       *server;
+  GstRTSPConnection   *conn;
+  GstRTSPClient       *client;
+  GstRTSPMessage      *request;
+  GstRTSPUrl          *uri;
+  GstRTSPMethod        method;
+  GstRTSPAuth         *auth;
+  GstRTSPToken        *token;
+  GstRTSPSession      *session;
+  GstRTSPSessionMedia *sessmedia;
+  GstRTSPMediaFactory *factory;
+  GstRTSPMedia        *media;
+  GstRTSPStream       *stream;
+  GstRTSPMessage      *response;
+};
+
+

Information passed around containing the context of a request.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstRTSPServer *server;

the server

 

GstRTSPConnection *conn;

the connection

 

GstRTSPClient *client;

the client

 

GstRTSPMessage *request;

the complete request

 

GstRTSPUrl *uri;

the complete url parsed from request +

 

GstRTSPMethod method;

the parsed method of uri +

 

GstRTSPAuth *auth;

the current auth object or NULL

 

GstRTSPToken *token;

authorisation token

 

GstRTSPSession *session;

the session, can be NULL

 

GstRTSPSessionMedia *sessmedia;

the session media for the url can be NULL

 

GstRTSPMediaFactory *factory;

the media factory for the url, can be NULL

 

GstRTSPMedia *media;

the media for the url can be NULL

 

GstRTSPStream *stream;

the stream for the url can be NULL

 

GstRTSPMessage *response;

the response

 
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/gst-rtsp-server-GstRTSPMediaFactoryURI.html b/docs/libs/html/gst-rtsp-server-GstRTSPMediaFactoryURI.html new file mode 100644 index 0000000..ba6ee82 --- /dev/null +++ b/docs/libs/html/gst-rtsp-server-GstRTSPMediaFactoryURI.html @@ -0,0 +1,196 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPMediaFactoryURI + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPMediaFactoryURI

+

GstRTSPMediaFactoryURI — A factory for URI sources

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + +
+GstRTSPMediaFactoryURI * + +gst_rtsp_media_factory_uri_new () +
+void + +gst_rtsp_media_factory_uri_set_uri () +
+gchar * + +gst_rtsp_media_factory_uri_get_uri () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstRTSPMediaFactoryURI
structGstRTSPMediaFactoryURIClass
+
+
+

Description

+

This specialized GstRTSPMediaFactory constructs media pipelines from a URI, +given with gst_rtsp_media_factory_uri_set_uri().

+

It will automatically demux and payload the different streams found in the +media at URL.

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_media_factory_uri_new ()

+
GstRTSPMediaFactoryURI *
+gst_rtsp_media_factory_uri_new (void);
+

Create a new GstRTSPMediaFactoryURI instance.

+
+

Returns

+

a new GstRTSPMediaFactoryURI object.

+

[transfer full]

+
+
+
+
+

gst_rtsp_media_factory_uri_set_uri ()

+
void
+gst_rtsp_media_factory_uri_set_uri (GstRTSPMediaFactoryURI *factory,
+                                    const gchar *uri);
+

Set the URI of the resource that will be streamed by this factory.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstRTSPMediaFactory

 

uri

the uri the stream

 
+
+
+
+
+

gst_rtsp_media_factory_uri_get_uri ()

+
gchar *
+gst_rtsp_media_factory_uri_get_uri (GstRTSPMediaFactoryURI *factory);
+

Get the URI that will provide media for this factory.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstRTSPMediaFactory

 
+
+
+

Returns

+

the configured URI. g_free() after usage.

+

[transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstRTSPMediaFactoryURI

+
struct GstRTSPMediaFactoryURI {
+  GstRTSPMediaFactory   parent;
+};
+
+

A media factory that creates a pipeline to play and uri.

+
+
+
+

struct GstRTSPMediaFactoryURIClass

+
struct GstRTSPMediaFactoryURIClass {
+  GstRTSPMediaFactoryClass  parent_class;
+};
+
+

The GstRTSPMediaFactoryURI class structure.

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/gst-rtsp-server-GstRTSPParams.html b/docs/libs/html/gst-rtsp-server-GstRTSPParams.html new file mode 100644 index 0000000..2831087 --- /dev/null +++ b/docs/libs/html/gst-rtsp-server-GstRTSPParams.html @@ -0,0 +1,149 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPParams + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPParams

+

GstRTSPParams — Param get and set implementation

+
+
+

Functions

+
++++ + + + + + + + + + + +
+GstRTSPResult + +gst_rtsp_params_get () +
+GstRTSPResult + +gst_rtsp_params_set () +
+
+
+

Description

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_params_get ()

+
GstRTSPResult
+gst_rtsp_params_get (GstRTSPClient *client,
+                     GstRTSPContext *ctx);
+

Get parameters (not implemented yet)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

client

a GstRTSPClient

 

ctx

a GstRTSPContext.

[transfer none]
+
+
+

Returns

+

a GstRTSPResult

+

+
+
+
+
+

gst_rtsp_params_set ()

+
GstRTSPResult
+gst_rtsp_params_set (GstRTSPClient *client,
+                     GstRTSPContext *ctx);
+

Set parameters (not implemented yet)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

client

a GstRTSPClient

 

ctx

a GstRTSPContext.

[transfer none]
+
+
+

Returns

+

a GstRTSPResult

+

+
+
+
+
+

Types and Values

+
+
+

See Also

+

GstRTSPClient

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gst-rtsp-server-GstRTSPPermissions.html b/docs/libs/html/gst-rtsp-server-GstRTSPPermissions.html new file mode 100644 index 0000000..d6cfc0f --- /dev/null +++ b/docs/libs/html/gst-rtsp-server-GstRTSPPermissions.html @@ -0,0 +1,428 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPPermissions + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPPermissions

+

GstRTSPPermissions — Roles and associated permissions

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPPermissions * + +gst_rtsp_permissions_new () +
+GstRTSPPermissions * + +gst_rtsp_permissions_ref () +
+void + +gst_rtsp_permissions_unref () +
+void + +gst_rtsp_permissions_add_role () +
+void + +gst_rtsp_permissions_add_role_valist () +
+void + +gst_rtsp_permissions_remove_role () +
const GstStructure * + +gst_rtsp_permissions_get_role () +
+gboolean + +gst_rtsp_permissions_is_allowed () +
+
+
+

Types and Values

+
++++ + + + + +
structGstRTSPPermissions
+
+
+

Description

+

The GstRTSPPermissions object contains an array of roles and associated +permissions. The roles are represented with a string and the permissions with +a generic GstStructure.

+

The permissions are deliberately kept generic. The possible values of the +roles and GstStructure keys and values are only determined by the GstRTSPAuth +object that performs the checks on the permissions and the current +GstRTSPToken.

+

As a convenience function, gst_rtsp_permissions_is_allowed() can be used to +check if the permissions contains a role that contains the boolean value +TRUE for the the given key.

+

Last reviewed on 2013-07-15 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_permissions_new ()

+
GstRTSPPermissions *
+gst_rtsp_permissions_new (void);
+

Create a new empty Authorization permissions.

+
+

Returns

+

a new empty authorization permissions.

+

[transfer full]

+
+
+
+
+

gst_rtsp_permissions_ref ()

+
GstRTSPPermissions *
+gst_rtsp_permissions_ref (GstRTSPPermissions *permissions);
+

Increase the refcount of this permissions.

+
+

Parameters

+
+++++ + + + + + +

permissions

The permissions to refcount

 
+
+
+

Returns

+

permissions +(for convenience when doing assignments).

+

[transfer full]

+
+
+
+
+

gst_rtsp_permissions_unref ()

+
void
+gst_rtsp_permissions_unref (GstRTSPPermissions *permissions);
+

Decrease the refcount of an permissions, freeing it if the refcount reaches 0.

+
+

Parameters

+
+++++ + + + + + +

permissions

the permissions to refcount.

[transfer full]
+
+
+
+
+

gst_rtsp_permissions_add_role ()

+
void
+gst_rtsp_permissions_add_role (GstRTSPPermissions *permissions,
+                               const gchar *role,
+                               const gchar *fieldname,
+                               ...);
+

Add a new role + to permissions + with the given variables. The fields +are the same layout as gst_structure_new().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

permissions

a GstRTSPPermissions

 

role

a role

 

fieldname

the first field name

 

...

additional arguments

 
+
+
+
+
+

gst_rtsp_permissions_add_role_valist ()

+
void
+gst_rtsp_permissions_add_role_valist (GstRTSPPermissions *permissions,
+                                      const gchar *role,
+                                      const gchar *fieldname,
+                                      va_list var_args);
+

Add a new role + to permissions + with the given variables. Structure fields +are set according to the varargs in a manner similar to gst_structure_new().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

permissions

a GstRTSPPermissions

 

role

a role

 

fieldname

the first field name

 

var_args

additional fields to add

 
+
+
+
+
+

gst_rtsp_permissions_remove_role ()

+
void
+gst_rtsp_permissions_remove_role (GstRTSPPermissions *permissions,
+                                  const gchar *role);
+

Remove all permissions for role + in permissions +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

permissions

a GstRTSPPermissions

 

role

a role

 
+
+
+
+
+

gst_rtsp_permissions_get_role ()

+
const GstStructure *
+gst_rtsp_permissions_get_role (GstRTSPPermissions *permissions,
+                               const gchar *role);
+

Get all permissions for role + in permissions +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

permissions

a GstRTSPPermissions

 

role

a role

 
+
+
+

Returns

+

the structure with permissions for role +. It +remains valid for as long as permissions +is valid.

+

[transfer none]

+
+
+
+
+

gst_rtsp_permissions_is_allowed ()

+
gboolean
+gst_rtsp_permissions_is_allowed (GstRTSPPermissions *permissions,
+                                 const gchar *role,
+                                 const gchar *permission);
+

Check if role + in permissions + is given permission for permission +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

permissions

a GstRTSPPermissions

 

role

a role

 

permission

a permission

 
+
+
+

Returns

+

TRUE if role +is allowed permission +.

+

+
+
+
+
+

Types and Values

+
+

struct GstRTSPPermissions

+
struct GstRTSPPermissions {
+  GstMiniObject mini_object;
+};
+
+

The opaque permissions structure. It is used to define the permissions +of objects in different roles.

+
+
+
+

See Also

+

GstRTSPToken, GstRTSPAuth

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gst-rtsp-server-GstRTSPSdp.html b/docs/libs/html/gst-rtsp-server-GstRTSPSdp.html new file mode 100644 index 0000000..88f0d70 --- /dev/null +++ b/docs/libs/html/gst-rtsp-server-GstRTSPSdp.html @@ -0,0 +1,135 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPSdp + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPSdp

+

GstRTSPSdp — Make SDP messages

+
+
+

Functions

+
++++ + + + + +
+gboolean + +gst_rtsp_sdp_from_media () +
+
+
+

Types and Values

+
++++ + + + + +
 GstSDPInfo
+
+
+

Description

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_sdp_from_media ()

+
gboolean
+gst_rtsp_sdp_from_media (GstSDPMessage *sdp,
+                         GstSDPInfo *info,
+                         GstRTSPMedia *media);
+

Add media + specific info to sdp +. info + is used to configure the connection +information in the SDP.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

sdp

a GstSDPMessage

 

info

a GstSDPInfo.

[transfer none]

media

a GstRTSPMedia.

[transfer none]
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

Types and Values

+
+

GstSDPInfo

+
typedef struct {
+  gboolean is_ipv6;
+  const gchar *server_ip;
+} GstSDPInfo;
+
+
+
+
+

See Also

+

GstRTSPMedia

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gst-rtsp-server-GstRTSPSessionMedia.html b/docs/libs/html/gst-rtsp-server-GstRTSPSessionMedia.html new file mode 100644 index 0000000..f36b686 --- /dev/null +++ b/docs/libs/html/gst-rtsp-server-GstRTSPSessionMedia.html @@ -0,0 +1,589 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPSessionMedia + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPSessionMedia

+

GstRTSPSessionMedia — Media managed in a session

+
+ +
+

Types and Values

+
++++ + + + + + + + + + + +
structGstRTSPSessionMedia
structGstRTSPSessionMediaClass
+
+
+

Description

+

The GstRTSPSessionMedia object manages a GstRTSPMedia with a given path.

+

With gst_rtsp_session_media_get_transport() and +gst_rtsp_session_media_set_transport() the transports of a GstRTSPStream of +the managed GstRTSPMedia can be retrieved and configured.

+

Use gst_rtsp_session_media_set_state() to control the media state and +transports.

+

Last reviewed on 2013-07-16 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_session_media_new ()

+
GstRTSPSessionMedia *
+gst_rtsp_session_media_new (const gchar *path,
+                            GstRTSPMedia *media);
+

Create a new GstRTSPSessionMedia that manages the streams +in media + for path +. media + should be prepared.

+

Ownership is taken of media +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

path

the path

 

media

the GstRTSPMedia.

[transfer full]
+
+
+

Returns

+

a new GstRTSPSessionMedia.

+

[transfer full]

+
+
+
+
+

gst_rtsp_session_media_matches ()

+
gboolean
+gst_rtsp_session_media_matches (GstRTSPSessionMedia *media,
+                                const gchar *path,
+                                gint *matched);
+

Check if the path of media + matches path +. It path + matches, the amount of +matched characters is returned in matched +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

media

a GstRTSPSessionMedia

 

path

a path

 

matched

the amount of matched characters of path +.

[out]
+
+
+

Returns

+

TRUE when path +matches the path of media +.

+

+
+
+
+
+

gst_rtsp_session_media_get_media ()

+
GstRTSPMedia *
+gst_rtsp_session_media_get_media (GstRTSPSessionMedia *media);
+

Get the GstRTSPMedia that was used when constructing media +

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPSessionMedia

 
+
+
+

Returns

+

the GstRTSPMedia of media +. Remains valid as long +as media +is valid.

+

[transfer none]

+
+
+
+
+

gst_rtsp_session_media_get_base_time ()

+
GstClockTime
+gst_rtsp_session_media_get_base_time (GstRTSPSessionMedia *media);
+

Get the base_time of the GstRTSPMedia in media +

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPSessionMedia

 
+
+
+

Returns

+

the base_time of the media.

+

+
+
+
+
+

gst_rtsp_session_media_get_rtpinfo ()

+
gchar *
+gst_rtsp_session_media_get_rtpinfo (GstRTSPSessionMedia *media);
+

Retrieve the RTP-Info header string for all streams in media + +with configured transports.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPSessionMedia

 
+
+
+

Returns

+

The RTP-Info as a string or +NULL when no RTP-Info could be generated, g_free() after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_rtsp_session_media_set_state ()

+
gboolean
+gst_rtsp_session_media_set_state (GstRTSPSessionMedia *media,
+                                  GstState state);
+

Tell the media object media + to change to state +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPSessionMedia

 

state

the new state

 
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

gst_rtsp_session_media_get_rtsp_state ()

+
GstRTSPState
+gst_rtsp_session_media_get_rtsp_state (GstRTSPSessionMedia *media);
+

Get the current RTSP state of media +.

+
+

Parameters

+
+++++ + + + + + +

media

a GstRTSPSessionMedia

 
+
+
+

Returns

+

the current RTSP state of media +.

+

+
+
+
+
+

gst_rtsp_session_media_set_rtsp_state ()

+
void
+gst_rtsp_session_media_set_rtsp_state (GstRTSPSessionMedia *media,
+                                       GstRTSPState state);
+

Set the RTSP state of media + to state +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPSessionMedia

 

state

a GstRTSPState

 
+
+
+
+
+

gst_rtsp_session_media_get_transport ()

+
GstRTSPStreamTransport *
+gst_rtsp_session_media_get_transport (GstRTSPSessionMedia *media,
+                                      guint idx);
+

Get a previously created GstRTSPStreamTransport for the stream at idx +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPSessionMedia

 

idx

the stream index

 
+
+
+

Returns

+

a GstRTSPStreamTransport that is valid until the +session of media +is unreffed.

+

[transfer none]

+
+
+
+
+

gst_rtsp_session_media_set_transport ()

+
GstRTSPStreamTransport *
+gst_rtsp_session_media_set_transport (GstRTSPSessionMedia *media,
+                                      GstRTSPStream *stream,
+                                      GstRTSPTransport *tr);
+

Configure the transport for stream + to tr + in media +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

media

a GstRTSPSessionMedia

 

stream

a GstRTSPStream

 

tr

a GstRTSPTransport.

[transfer full]
+
+
+

Returns

+

the new or updated GstRTSPStreamTransport for stream +.

+

[transfer none]

+
+
+
+
+

gst_rtsp_session_media_alloc_channels ()

+
gboolean
+gst_rtsp_session_media_alloc_channels (GstRTSPSessionMedia *media,
+                                       GstRTSPRange *range);
+

Fill range + with the next available min and max channels for +interleaved transport.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

media

a GstRTSPSessionMedia

 

range

a GstRTSPRange.

[out]
+
+
+

Returns

+

TRUE on success.

+

+
+
+
+
+

Types and Values

+
+

struct GstRTSPSessionMedia

+
struct GstRTSPSessionMedia {
+  GObject  parent;
+};
+
+

State of a client session regarding a specific media identified by path.

+
+
+
+

struct GstRTSPSessionMediaClass

+
struct GstRTSPSessionMediaClass {
+  GObjectClass  parent_class;
+};
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/gst-rtsp-server-GstRTSPStreamTransport.html b/docs/libs/html/gst-rtsp-server-GstRTSPStreamTransport.html new file mode 100644 index 0000000..6ae49fe --- /dev/null +++ b/docs/libs/html/gst-rtsp-server-GstRTSPStreamTransport.html @@ -0,0 +1,851 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPStreamTransport + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPStreamTransport

+

GstRTSPStreamTransport — A media stream transport configuration

+
+
+

Functions

+ +
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstRTSPStreamTransport
structGstRTSPStreamTransportClass
+
+
+

Description

+

The GstRTSPStreamTransport configures the transport used by a +GstRTSPStream. It is usually manages by a GstRTSPSessionMedia object.

+

With gst_rtsp_stream_transport_set_callbacks(), callbacks can be configured +to handle the RTP and RTCP packets from the stream, for example when they +need to be sent over TCP.

+

With gst_rtsp_stream_transport_set_active() the transports are added and +removed from the stream.

+

A GstRTSPStream will call gst_rtsp_stream_transport_keep_alive() when RTCP +is received from the client. It will also call +gst_rtsp_stream_transport_set_timed_out() when a receiver has timed out.

+

Last reviewed on 2013-07-16 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_stream_transport_new ()

+
GstRTSPStreamTransport *
+gst_rtsp_stream_transport_new (GstRTSPStream *stream,
+                               GstRTSPTransport *tr);
+

Create a new GstRTSPStreamTransport that can be used to manage +stream + with transport tr +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstRTSPStream

 

tr

a GstRTSPTransport.

[transfer full]
+
+
+

Returns

+

a new GstRTSPStreamTransport.

+

[transfer full]

+
+
+
+
+

gst_rtsp_stream_transport_get_stream ()

+
GstRTSPStream *
+gst_rtsp_stream_transport_get_stream (GstRTSPStreamTransport *trans);
+

Get the GstRTSPStream used when constructing trans +.

+
+

Parameters

+
+++++ + + + + + +

trans

a GstRTSPStreamTransport

 
+
+
+

Returns

+

the stream used when constructing trans +.

+

[transfer none]

+
+
+
+
+

gst_rtsp_stream_transport_get_transport ()

+
const GstRTSPTransport *
+gst_rtsp_stream_transport_get_transport
+                               (GstRTSPStreamTransport *trans);
+

Get the transport configured in trans +.

+
+

Parameters

+
+++++ + + + + + +

trans

a GstRTSPStreamTransport

 
+
+
+

Returns

+

the transport configured in trans +. It remains +valid for as long as trans +is valid.

+

[transfer none]

+
+
+
+
+

gst_rtsp_stream_transport_set_transport ()

+
void
+gst_rtsp_stream_transport_set_transport
+                               (GstRTSPStreamTransport *trans,
+                                GstRTSPTransport *tr);
+

Set tr + as the client transport. This function takes ownership of the +passed tr +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

a GstRTSPStreamTransport

 

tr

a client GstRTSPTransport.

[transfer full]
+
+
+
+
+

gst_rtsp_stream_transport_get_url ()

+
const GstRTSPUrl *
+gst_rtsp_stream_transport_get_url (GstRTSPStreamTransport *trans);
+

Get the url configured in trans +.

+
+

Parameters

+
+++++ + + + + + +

trans

a GstRTSPStreamTransport

 
+
+
+

Returns

+

the url configured in trans +. It remains +valid for as long as trans +is valid.

+

[transfer none]

+
+
+
+
+

gst_rtsp_stream_transport_set_url ()

+
void
+gst_rtsp_stream_transport_set_url (GstRTSPStreamTransport *trans,
+                                   const GstRTSPUrl *url);
+

Set url + as the client url.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

a GstRTSPStreamTransport

 

url

a client GstRTSPUrl.

[transfer none]
+
+
+
+
+

gst_rtsp_stream_transport_get_rtpinfo ()

+
gchar *
+gst_rtsp_stream_transport_get_rtpinfo (GstRTSPStreamTransport *trans,
+                                       GstClockTime start_time);
+

Get the RTP-Info string for trans + and start_time +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

a GstRTSPStreamTransport

 

start_time

a star time

 
+
+
+

Returns

+

the RTPInfo string for trans +and start_time +or NULL when the RTP-Info could not be +determined. g_free() after usage.

+

[transfer full][nullable]

+
+
+
+
+

GstRTSPSendFunc ()

+
gboolean
+(*GstRTSPSendFunc) (GstBuffer *buffer,
+                    guint8 channel,
+                    gpointer user_data);
+

Function registered with gst_rtsp_stream_transport_set_callbacks() and +called when buffer + must be sent on channel +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer

 

channel

a channel

 

user_data

user data

 
+
+
+

Returns

+

TRUE on success

+

+
+
+
+
+

gst_rtsp_stream_transport_set_callbacks ()

+
void
+gst_rtsp_stream_transport_set_callbacks
+                               (GstRTSPStreamTransport *trans,
+                                GstRTSPSendFunc send_rtp,
+                                GstRTSPSendFunc send_rtcp,
+                                gpointer user_data,
+                                GDestroyNotify notify);
+

Install callbacks that will be called when data for a stream should be sent +to a client. This is usually used when sending RTP/RTCP over TCP.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

trans

a GstRTSPStreamTransport

 

send_rtp

a callback called when RTP should be sent.

[scope notified]

send_rtcp

a callback called when RTCP should be sent.

[scope notified]

user_data

user data passed to callbacks.

[closure]

notify

called with the user_data when no longer needed.

[allow-none]
+
+
+
+
+

GstRTSPKeepAliveFunc ()

+
void
+(*GstRTSPKeepAliveFunc) (gpointer user_data);
+

Function registered with gst_rtsp_stream_transport_set_keepalive() and called +when the stream is active.

+
+

Parameters

+
+++++ + + + + + +

user_data

user data

 
+
+
+
+
+

gst_rtsp_stream_transport_set_keepalive ()

+
void
+gst_rtsp_stream_transport_set_keepalive
+                               (GstRTSPStreamTransport *trans,
+                                GstRTSPKeepAliveFunc keep_alive,
+                                gpointer user_data,
+                                GDestroyNotify notify);
+

Install callbacks that will be called when RTCP packets are received from the +receiver of trans +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

trans

a GstRTSPStreamTransport

 

keep_alive

a callback called when the receiver is active.

[scope notified]

user_data

user data passed to callback.

[closure]

notify

called with the user_data when no longer needed.

[allow-none]
+
+
+
+
+

gst_rtsp_stream_transport_keep_alive ()

+
void
+gst_rtsp_stream_transport_keep_alive (GstRTSPStreamTransport *trans);
+

Signal the installed keep_alive callback for trans +.

+
+

Parameters

+
+++++ + + + + + +

trans

a GstRTSPStreamTransport

 
+
+
+
+
+

gst_rtsp_stream_transport_set_active ()

+
gboolean
+gst_rtsp_stream_transport_set_active (GstRTSPStreamTransport *trans,
+                                      gboolean active);
+

Activate or deactivate datatransfer configured in trans +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

a GstRTSPStreamTransport

 

active

new state of trans +

 
+
+
+

Returns

+

TRUE when the state was changed.

+

+
+
+
+
+

gst_rtsp_stream_transport_set_timed_out ()

+
void
+gst_rtsp_stream_transport_set_timed_out
+                               (GstRTSPStreamTransport *trans,
+                                gboolean timedout);
+

Set the timed out state of trans + to timedout +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

a GstRTSPStreamTransport

 

timedout

timed out value

 
+
+
+
+
+

gst_rtsp_stream_transport_is_timed_out ()

+
gboolean
+gst_rtsp_stream_transport_is_timed_out
+                               (GstRTSPStreamTransport *trans);
+

Check if trans + is timed out.

+
+

Parameters

+
+++++ + + + + + +

trans

a GstRTSPStreamTransport

 
+
+
+

Returns

+

TRUE if trans +timed out.

+

+
+
+
+
+

gst_rtsp_stream_transport_send_rtcp ()

+
gboolean
+gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport *trans,
+                                     GstBuffer *buffer);
+

Send buffer + to the installed RTCP callback for trans +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

a GstRTSPStreamTransport

 

buffer

a GstBuffer.

[transfer none]
+
+
+

Returns

+

TRUE on success

+

+
+
+
+
+

gst_rtsp_stream_transport_send_rtp ()

+
gboolean
+gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport *trans,
+                                    GstBuffer *buffer);
+

Send buffer + to the installed RTP callback for trans +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

a GstRTSPStreamTransport

 

buffer

a GstBuffer.

[transfer none]
+
+
+

Returns

+

TRUE on success

+

+
+
+
+
+

Types and Values

+
+

struct GstRTSPStreamTransport

+
struct GstRTSPStreamTransport {
+  GObject              parent;
+};
+
+

A Transport description for a stream

+
+

Members

+
+++++ + + + + + +

GObject parent;

parent instance

 
+
+
+
+
+

struct GstRTSPStreamTransportClass

+
struct GstRTSPStreamTransportClass {
+  GObjectClass parent_class;
+};
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/gst-rtsp-server-GstRTSPThreadPool.html b/docs/libs/html/gst-rtsp-server-GstRTSPThreadPool.html new file mode 100644 index 0000000..f793fe9 --- /dev/null +++ b/docs/libs/html/gst-rtsp-server-GstRTSPThreadPool.html @@ -0,0 +1,592 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPThreadPool + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPThreadPool

+

GstRTSPThreadPool — A pool of threads

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPThread * + +gst_rtsp_thread_new () +
+GstRTSPThread * + +gst_rtsp_thread_ref () +
+void + +gst_rtsp_thread_unref () +
+gboolean + +gst_rtsp_thread_reuse () +
+void + +gst_rtsp_thread_stop () +
+GstRTSPThreadPool * + +gst_rtsp_thread_pool_new () +
+gint + +gst_rtsp_thread_pool_get_max_threads () +
+void + +gst_rtsp_thread_pool_set_max_threads () +
+GstRTSPThread * + +gst_rtsp_thread_pool_get_thread () +
+void + +gst_rtsp_thread_pool_cleanup () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + +
enumGstRTSPThreadType
structGstRTSPThread
structGstRTSPThreadPool
structGstRTSPThreadPoolClass
+
+
+

Description

+

A GstRTSPThreadPool manages reusable threads for various server tasks. +Currently the defined thread types can be found in GstRTSPThreadType.

+

Threads of type GST_RTSP_THREAD_TYPE_CLIENT are used to handle requests from +a connected client. With gst_rtsp_thread_pool_get_max_threads() a maximum +number of threads can be set after which the pool will start to reuse the +same thread for multiple clients.

+

Threads of type GST_RTSP_THREAD_TYPE_MEDIA will be used to perform the state +changes of the media pipelines and handle its bus messages.

+

gst_rtsp_thread_pool_get_thread() can be used to create a GstRTSPThread +object of the right type. The thread object contains a mainloop and context +that run in a seperate thread and can be used to attached sources to.

+

gst_rtsp_thread_reuse() can be used to reuse a thread for multiple purposes. +If all gst_rtsp_thread_reuse() calls are matched with a +gst_rtsp_thread_stop() call, the mainloop will be quit and the thread will +stop.

+

To configure the threads, a subclass of this object should be made and the +virtual methods should be overriden to implement the desired functionality.

+

Last reviewed on 2013-07-11 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_thread_new ()

+
GstRTSPThread *
+gst_rtsp_thread_new (GstRTSPThreadType type);
+

Create a new thread object that can run a mainloop.

+
+

Parameters

+
+++++ + + + + + +

type

the thread type

 
+
+
+

Returns

+

a GstRTSPThread.

+

[transfer full]

+
+
+
+
+

gst_rtsp_thread_ref ()

+
GstRTSPThread *
+gst_rtsp_thread_ref (GstRTSPThread *thread);
+

Increase the refcount of this thread.

+
+

Parameters

+
+++++ + + + + + +

thread

The thread to refcount

 
+
+
+

Returns

+

thread +(for convenience when doing assignments).

+

[transfer full]

+
+
+
+
+

gst_rtsp_thread_unref ()

+
void
+gst_rtsp_thread_unref (GstRTSPPermissions *thread);
+

Decrease the refcount of an thread, freeing it if the refcount reaches 0.

+
+

Parameters

+
+++++ + + + + + +

thread

the thread to refcount.

[transfer full]
+
+
+
+
+

gst_rtsp_thread_reuse ()

+
gboolean
+gst_rtsp_thread_reuse (GstRTSPThread *thread);
+

Reuse the mainloop of thread +

+
+

Parameters

+
+++++ + + + + + +

thread

a GstRTSPThread.

[transfer none]
+
+
+

Returns

+

TRUE if the mainloop could be reused

+

+
+
+
+
+

gst_rtsp_thread_stop ()

+
void
+gst_rtsp_thread_stop (GstRTSPThread *thread);
+

Stop and unref thread +. When no threads are using the mainloop, the thread +will be stopped and the final ref to thread + will be released.

+
+

Parameters

+
+++++ + + + + + +

thread

a GstRTSPThread.

[transfer full]
+
+
+
+
+

gst_rtsp_thread_pool_new ()

+
GstRTSPThreadPool *
+gst_rtsp_thread_pool_new (void);
+

Create a new GstRTSPThreadPool instance.

+
+

Returns

+

a new GstRTSPThreadPool.

+

[transfer full]

+
+
+
+
+

gst_rtsp_thread_pool_get_max_threads ()

+
gint
+gst_rtsp_thread_pool_get_max_threads (GstRTSPThreadPool *pool);
+

Get the maximum number of threads used for client connections. +See gst_rtsp_thread_pool_set_max_threads().

+
+

Parameters

+
+++++ + + + + + +

pool

a GstRTSPThreadPool

 
+
+
+

Returns

+

the maximum number of threads.

+

+
+
+
+
+

gst_rtsp_thread_pool_set_max_threads ()

+
void
+gst_rtsp_thread_pool_set_max_threads (GstRTSPThreadPool *pool,
+                                      gint max_threads);
+

Set the maximum threads used by the pool to handle client requests. +A value of 0 will use the pool mainloop, a value of -1 will use an +unlimited number of threads.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

a GstRTSPThreadPool

 

max_threads

maximum threads

 
+
+
+
+
+

gst_rtsp_thread_pool_get_thread ()

+
GstRTSPThread *
+gst_rtsp_thread_pool_get_thread (GstRTSPThreadPool *pool,
+                                 GstRTSPThreadType type,
+                                 GstRTSPContext *ctx);
+

Get a new GstRTSPThread for type + and ctx +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pool

a GstRTSPThreadPool

 

type

the GstRTSPThreadType

 

ctx

a GstRTSPContext.

[transfer none]
+
+
+

Returns

+

a new GstRTSPThread, gst_rtsp_thread_stop() after usage.

+

[transfer full]

+
+
+
+
+

gst_rtsp_thread_pool_cleanup ()

+
void
+gst_rtsp_thread_pool_cleanup (void);
+

Wait for all tasks to be stopped and free all allocated resources. This is +mainly used in test suites to ensure proper cleanup of internal data +structures.

+
+
+
+

Types and Values

+
+

enum GstRTSPThreadType

+

Different thread types

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_RTSP_THREAD_TYPE_CLIENT

+

a thread to handle the client communication

+
 

GST_RTSP_THREAD_TYPE_MEDIA

+

a thread to handle media

+
 
+
+
+
+
+

struct GstRTSPThread

+
struct GstRTSPThread {
+  GstMiniObject mini_object;
+
+  GstRTSPThreadType type;
+  GMainContext *context;
+  GMainLoop *loop;
+};
+
+

Structure holding info about a mainloop running in a thread

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GstMiniObject mini_object;

parent GstMiniObject

 

GstRTSPThreadType type;

the thread type

 

GMainContext *context;

a GMainContext

 

GMainLoop *loop;

a GMainLoop

 
+
+
+
+
+

struct GstRTSPThreadPool

+
struct GstRTSPThreadPool {
+  GObject       parent;
+};
+
+

The thread pool structure.

+
+
+
+

struct GstRTSPThreadPoolClass

+
struct GstRTSPThreadPoolClass {
+  GObjectClass  parent_class;
+
+  GThreadPool *pool;
+
+  GstRTSPThread * (*get_thread)        (GstRTSPThreadPool *pool,
+                                        GstRTSPThreadType type,
+                                        GstRTSPContext *ctx);
+  void            (*configure_thread)  (GstRTSPThreadPool *pool,
+                                        GstRTSPThread * thread,
+                                        GstRTSPContext *ctx);
+
+  void            (*thread_enter)      (GstRTSPThreadPool *pool,
+                                        GstRTSPThread *thread);
+  void            (*thread_leave)      (GstRTSPThreadPool *pool,
+                                        GstRTSPThread *thread);
+};
+
+

Class for managing threads.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GObjectClass parent_class;

  

GThreadPool *pool;

a GThreadPool used internally

 

get_thread ()

this function should make or reuse an existing thread that runs +a mainloop.

 

configure_thread ()

configure a thread object. this vmethod is called when +a new thread has been created and should be configured.

 

thread_enter ()

called from the thread when it is entered

 

thread_leave ()

called from the thread when it is left

 
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/gst-rtsp-server-GstRTSPToken.html b/docs/libs/html/gst-rtsp-server-GstRTSPToken.html new file mode 100644 index 0000000..9bd5be3 --- /dev/null +++ b/docs/libs/html/gst-rtsp-server-GstRTSPToken.html @@ -0,0 +1,443 @@ + + + + +GStreamer RTSP Server Reference Manual: GstRTSPToken + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRTSPToken

+

GstRTSPToken — Roles and permissions for a client

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRTSPToken * + +gst_rtsp_token_new_empty () +
+GstRTSPToken * + +gst_rtsp_token_new () +
+GstRTSPToken * + +gst_rtsp_token_new_valist () +
+GstRTSPToken * + +gst_rtsp_token_ref () +
+void + +gst_rtsp_token_unref () +
const GstStructure * + +gst_rtsp_token_get_structure () +
+GstStructure * + +gst_rtsp_token_writable_structure () +
const gchar * + +gst_rtsp_token_get_string () +
+gboolean + +gst_rtsp_token_is_allowed () +
+
+
+

Types and Values

+
++++ + + + + +
structGstRTSPToken
+
+
+

Description

+

A GstRTSPToken contains the permissions and roles of the user +performing the current request. A token is usually created when a user is +authenticated by the GstRTSPAuth object and is then placed as the current +token for the current request.

+

GstRTSPAuth can use the token and its contents to check authorization for +various operations by comparing the token to the GstRTSPPermissions of the +object.

+

The accepted values of the token are entirely defined by the GstRTSPAuth +object that implements the security policy.

+

Last reviewed on 2013-07-15 (1.0.0)

+
+
+

Functions

+
+

gst_rtsp_token_new_empty ()

+
GstRTSPToken *
+gst_rtsp_token_new_empty (void);
+

Create a new empty Authorization token.

+
+

Returns

+

a new empty authorization token.

+

[transfer full]

+
+
+
+
+

gst_rtsp_token_new ()

+
GstRTSPToken *
+gst_rtsp_token_new (const gchar *firstfield,
+                    ...);
+

Create a new Authorization token with the given fieldnames and values. +Arguments are given similar to gst_structure_new().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

firstfield

the first fieldname

 

...

additional arguments

 
+
+
+

Returns

+

a new authorization token.

+

[transfer full]

+
+
+
+
+

gst_rtsp_token_new_valist ()

+
GstRTSPToken *
+gst_rtsp_token_new_valist (const gchar *firstfield,
+                           va_list var_args);
+

Create a new Authorization token with the given fieldnames and values. +Arguments are given similar to gst_structure_new_valist().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

firstfield

the first fieldname

 

var_args

additional arguments

 
+
+
+

Returns

+

a new authorization token.

+

[transfer full]

+
+
+
+
+

gst_rtsp_token_ref ()

+
GstRTSPToken *
+gst_rtsp_token_ref (GstRTSPToken *token);
+

Increase the refcount of this token.

+
+

Parameters

+
+++++ + + + + + +

token

The token to refcount

 
+
+
+

Returns

+

token +(for convenience when doing assignments).

+

[transfer full]

+
+
+
+
+

gst_rtsp_token_unref ()

+
void
+gst_rtsp_token_unref (GstRTSPToken *token);
+

Decrease the refcount of an token, freeing it if the refcount reaches 0.

+
+

Parameters

+
+++++ + + + + + +

token

the token to refcount.

[transfer full]
+
+
+
+
+

gst_rtsp_token_get_structure ()

+
const GstStructure *
+gst_rtsp_token_get_structure (GstRTSPToken *token);
+

Access the structure of the token.

+
+

Parameters

+
+++++ + + + + + +

token

The GstRTSPToken.

 
+
+
+

Returns

+

The structure of the token. The structure is still +owned by the token, which means that you should not free it and that the +pointer becomes invalid when you free the token.

+

MT safe.

+

[transfer none]

+
+
+
+
+

gst_rtsp_token_writable_structure ()

+
GstStructure *
+gst_rtsp_token_writable_structure (GstRTSPToken *token);
+

Get a writable version of the structure.

+
+

Parameters

+
+++++ + + + + + +

token

The GstRTSPToken.

 
+
+
+

Returns

+

The structure of the token. The structure is still +owned by the token, which means that you should not free it and that the +pointer becomes invalid when you free the token. This function checks if +token +is writable and will never return NULL.

+

MT safe.

+

[transfer none]

+
+
+
+
+

gst_rtsp_token_get_string ()

+
const gchar *
+gst_rtsp_token_get_string (GstRTSPToken *token,
+                           const gchar *field);
+

Get the string value of field + in token +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

token

a GstRTSPToken

 

field

a field name

 
+
+
+

Returns

+

the string value of field +in +token +or NULL when field +is not defined in token +. The string +becomes invalid when you free token +.

+

[transfer none][nullable]

+
+
+
+
+

gst_rtsp_token_is_allowed ()

+
gboolean
+gst_rtsp_token_is_allowed (GstRTSPToken *token,
+                           const gchar *field);
+

Check if token + has a boolean field + and if it is set to TRUE.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

token

a GstRTSPToken

 

field

a field name

 
+
+
+

Returns

+

TRUE if token +has a boolean field named field +set to TRUE.

+

+
+
+
+
+

Types and Values

+
+

struct GstRTSPToken

+
struct GstRTSPToken {
+  GstMiniObject mini_object;
+};
+
+

An opaque object used for checking authorisations. +It is generated after successful authentication.

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/home.png b/docs/libs/html/home.png new file mode 100644 index 0000000..9346b33 Binary files /dev/null and b/docs/libs/html/home.png differ diff --git a/docs/libs/html/index.html b/docs/libs/html/index.html new file mode 100644 index 0000000..d6b8af9 --- /dev/null +++ b/docs/libs/html/index.html @@ -0,0 +1,93 @@ + + + + +GStreamer RTSP Server Reference Manual: GStreamer RTSP Server Reference Manual + + + + + + + +
+
+
+
+

+ for GStreamer RTSP Server 1.4.5 +

+
+
+
+
+
+
+
+GstRTSPServer — The main server object +
+
+GstRTSPClient — A client connection state +
+
+GstRTSPContext — A client request context +
+
+GstRTSPMountPoints — Map a path to media +
+
+GstRTSPMediaFactory — A factory for media pipelines +
+
+GstRTSPMediaFactoryURI — A factory for URI sources +
+
+GstRTSPMedia — The media pipeline +
+
+GstRTSPStream — A media stream +
+
+GstRTSPSessionPool — An object for managing sessions +
+
+GstRTSPSession — An object to manage media +
+
+GstRTSPSessionMedia — Media managed in a session +
+
+GstRTSPStreamTransport — A media stream transport configuration +
+
+GstRTSPSdp — Make SDP messages +
+
+GstRTSPAddressPool — A pool of network addresses +
+
+GstRTSPThreadPool — A pool of threads +
+
+GstRTSPAuth — Authentication and authorization +
+
+GstRTSPToken — Roles and permissions for a client +
+
+GstRTSPPermissions — Roles and associated permissions +
+
+GstRTSPParams — Param get and set implementation +
+
+
Object Hierarchy
+
API Index
+
Annotation Glossary
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/index.sgml b/docs/libs/html/index.sgml new file mode 100644 index 0000000..a3ac202 --- /dev/null +++ b/docs/libs/html/index.sgml @@ -0,0 +1,533 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/libs/html/left-insensitive.png b/docs/libs/html/left-insensitive.png new file mode 100644 index 0000000..3269393 Binary files /dev/null and b/docs/libs/html/left-insensitive.png differ diff --git a/docs/libs/html/left.png b/docs/libs/html/left.png new file mode 100644 index 0000000..2abde03 Binary files /dev/null and b/docs/libs/html/left.png differ diff --git a/docs/libs/html/right-insensitive.png b/docs/libs/html/right-insensitive.png new file mode 100644 index 0000000..4c95785 Binary files /dev/null and b/docs/libs/html/right-insensitive.png differ diff --git a/docs/libs/html/right.png b/docs/libs/html/right.png new file mode 100644 index 0000000..76260ec Binary files /dev/null and b/docs/libs/html/right.png differ diff --git a/docs/libs/html/rtsp-server-hierarchy.html b/docs/libs/html/rtsp-server-hierarchy.html new file mode 100644 index 0000000..4d752f2 --- /dev/null +++ b/docs/libs/html/rtsp-server-hierarchy.html @@ -0,0 +1,42 @@ + + + + +GStreamer RTSP Server Reference Manual: Object Hierarchy + + + + + + + + + + + + + + + + +
+

+Object Hierarchy

+
+    GObject
+    ├── GstRTSPAuth
+    ├── GstRTSPMountPoints
+    ├── GstRTSPMediaFactory
+    ├── GstRTSPMedia
+    ├── GstRTSPServer
+    ├── GstRTSPSessionPool
+    ├── GstRTSPSession
+    ├── GstRTSPClient
+    ╰── GstRTSPStream
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/style.css b/docs/libs/html/style.css new file mode 100644 index 0000000..c141ddd --- /dev/null +++ b/docs/libs/html/style.css @@ -0,0 +1,476 @@ +body +{ + font-family: cantarell, sans-serif; +} +.synopsis, .classsynopsis +{ + /* tango:aluminium 1/2 */ + background: #eeeeec; + background: rgba(238, 238, 236, 0.5); + border: solid 1px rgb(238, 238, 236); + padding: 0.5em; +} +.programlisting +{ + /* tango:sky blue 0/1 */ + /* fallback for no rgba support */ + background: #e6f3ff; + border: solid 1px #729fcf; + background: rgba(114, 159, 207, 0.1); + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0.5em; +} +.variablelist +{ + padding: 4px; + margin-left: 3em; +} +.variablelist td:first-child +{ + vertical-align: top; +} + +div.gallery-float +{ + float: left; + padding: 10px; +} +div.gallery-float img +{ + border-style: none; +} +div.gallery-spacer +{ + clear: both; +} + +a, a:visited +{ + text-decoration: none; + /* tango:sky blue 2 */ + color: #3465a4; +} +a:hover +{ + text-decoration: underline; + /* tango:sky blue 1 */ + color: #729fcf; +} + +div.informaltable table +{ + border-collapse: separate; + border-spacing: 1em 0.5em; + border: none; +} + +div.informaltable table td, div.informaltable table th +{ + vertical-align: top; +} + +.function_type, +.variable_type, +.property_type, +.signal_type, +.parameter_name, +.struct_member_name, +.union_member_name, +.define_keyword, +.datatype_keyword, +.typedef_keyword +{ + text-align: right; +} + +/* dim non-primary columns */ +.c_punctuation, +.function_type, +.variable_type, +.property_type, +.signal_type, +.define_keyword, +.datatype_keyword, +.typedef_keyword, +.property_flags, +.signal_flags, +.parameter_annotations, +.enum_member_annotations, +.struct_member_annotations, +.union_member_annotations +{ + color: #888a85; +} + +.function_type a, +.function_type a:visited, +.function_type a:hover, +.property_type a, +.property_type a:visited, +.property_type a:hover, +.signal_type a, +.signal_type a:visited, +.signal_type a:hover, +.signal_flags a, +.signal_flags a:visited, +.signal_flags a:hover +{ + color: #729fcf; +} + +td p +{ + margin: 0.25em; +} + +div.table table +{ + border-collapse: collapse; + border-spacing: 0px; + /* tango:aluminium 3 */ + border: solid 1px #babdb6; +} + +div.table table td, div.table table th +{ + /* tango:aluminium 3 */ + border: solid 1px #babdb6; + padding: 3px; + vertical-align: top; +} + +div.table table th +{ + /* tango:aluminium 2 */ + background-color: #d3d7cf; +} + +h4 +{ + color: #555753; +} + +hr +{ + /* tango:aluminium 1 */ + color: #d3d7cf; + background: #d3d7cf; + border: none 0px; + height: 1px; + clear: both; + margin: 2.0em 0em 2.0em 0em; +} + +dl.toc dt +{ + padding-bottom: 0.25em; +} + +dl.toc > dd > dl > dt +{ + padding-top: 0.25em; + padding-bottom: 0.25em; +} + +dl.toc > dt +{ + padding-top: 1em; + padding-bottom: 0.5em; + font-weight: bold; +} + +.parameter +{ + font-style: normal; +} + +.footer +{ + padding-top: 3.5em; + /* tango:aluminium 3 */ + color: #babdb6; + text-align: center; + font-size: 80%; +} + +.informalfigure, +.figure +{ + margin: 1em; +} + +.informalexample, +.example +{ + margin-top: 1em; + margin-bottom: 1em; +} + +.warning +{ + /* tango:orange 0/1 */ + background: #ffeed9; + background: rgba(252, 175, 62, 0.1); + border-color: #ffb04f; + border-color: rgba(252, 175, 62, 0.2); +} +.note +{ + /* tango:chameleon 0/0.5 */ + background: #d8ffb2; + background: rgba(138, 226, 52, 0.1); + border-color: #abf562; + border-color: rgba(138, 226, 52, 0.2); +} +div.blockquote +{ + border-color: #eeeeec; +} +.note, .warning, div.blockquote +{ + padding: 0.5em; + border-width: 1px; + border-style: solid; + margin: 2em; +} +.note p, .warning p +{ + margin: 0; +} + +div.warning h3.title, +div.note h3.title +{ + display: none; +} + +p + div.section +{ + margin-top: 1em; +} + +div.refnamediv, +div.refsynopsisdiv, +div.refsect1, +div.refsect2, +div.toc, +div.section +{ + margin-bottom: 1em; +} + +/* blob links */ +h2 .extralinks, h3 .extralinks +{ + float: right; + /* tango:aluminium 3 */ + color: #babdb6; + font-size: 80%; + font-weight: normal; +} + +.lineart +{ + color: #d3d7cf; + font-weight: normal; +} + +.annotation +{ + /* tango:aluminium 5 */ + color: #555753; + font-weight: normal; +} + +.structfield +{ + font-style: normal; + font-weight: normal; +} + +acronym,abbr +{ + border-bottom: 1px dotted gray; +} + +/* code listings */ + +.listing_code .programlisting .normal, +.listing_code .programlisting .normal a, +.listing_code .programlisting .number, +.listing_code .programlisting .cbracket, +.listing_code .programlisting .symbol { color: #555753; } +.listing_code .programlisting .comment, +.listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ +.listing_code .programlisting .function, +.listing_code .programlisting .function a, +.listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ +.listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */ +.listing_code .programlisting .keyword, +.listing_code .programlisting .usertype, +.listing_code .programlisting .type, +.listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */ + +.listing_frame { + /* tango:sky blue 1 */ + border: solid 1px #729fcf; + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0px; +} + +.listing_lines, .listing_code { + margin-top: 0px; + margin-bottom: 0px; + padding: 0.5em; +} +.listing_lines { + /* tango:sky blue 0.5 */ + background: #a6c5e3; + background: rgba(114, 159, 207, 0.2); + /* tango:aluminium 6 */ + color: #2e3436; +} +.listing_code { + /* tango:sky blue 0 */ + background: #e6f3ff; + background: rgba(114, 159, 207, 0.1); +} +.listing_code .programlisting { + /* override from previous */ + border: none 0px; + padding: 0px; + background: none; +} +.listing_lines pre, .listing_code pre { + margin: 0px; +} + +@media screen { + sup a.footnote + { + position: relative; + top: 0em ! important; + } + /* this is needed so that the local anchors are displayed below the naviagtion */ + div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] + { + display: inline-block; + position: relative; + top:-5em; + } + /* this seems to be a bug in the xsl style sheets when generating indexes */ + div.index div.index + { + top: 0em; + } + /* make space for the fixed navigation bar and add space at the bottom so that + * link targets appear somewhat close to top + */ + body + { + padding-top: 2.5em; + padding-bottom: 500px; + max-width: 60em; + } + p + { + max-width: 60em; + } + /* style and size the navigation bar */ + table.navigation#top + { + position: fixed; + background: #e2e2e2; + border-bottom: solid 1px #babdb6; + border-spacing: 5px; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + z-index: 10; + } + table.navigation#top td + { + padding-left: 6px; + padding-right: 6px; + } + .navigation a, .navigation a:visited + { + /* tango:sky blue 3 */ + color: #204a87; + } + .navigation a:hover + { + /* tango:sky blue 2 */ + color: #3465a4; + } + td.shortcuts + { + /* tango:sky blue 2 */ + color: #3465a4; + font-size: 80%; + white-space: nowrap; + } + td.shortcuts .dim + { + color: #babdb6; + } + .navigation .title + { + font-size: 80%; + max-width: none; + margin: 0px; + font-weight: normal; + } +} +@media screen and (min-width: 60em) { + /* screen larger than 60em */ + body { margin: auto; } +} +@media screen and (max-width: 60em) { + /* screen less than 60em */ + #nav_hierarchy { display: none; } + #nav_interfaces { display: none; } + #nav_prerequisites { display: none; } + #nav_derived_interfaces { display: none; } + #nav_implementations { display: none; } + #nav_child_properties { display: none; } + #nav_style_properties { display: none; } + #nav_index { display: none; } + #nav_glossary { display: none; } + .gallery_image { display: none; } + .property_flags { display: none; } + .signal_flags { display: none; } + .parameter_annotations { display: none; } + .enum_member_annotations { display: none; } + .struct_member_annotations { display: none; } + .union_member_annotations { display: none; } + /* now that a column is hidden, optimize space */ + col.parameters_name { width: auto; } + col.parameters_description { width: auto; } + col.struct_members_name { width: auto; } + col.struct_members_description { width: auto; } + col.enum_members_name { width: auto; } + col.enum_members_description { width: auto; } + col.union_members_name { width: auto; } + col.union_members_description { width: auto; } + .listing_lines { display: none; } +} +@media print { + table.navigation { + visibility: collapse; + display: none; + } + div.titlepage table.navigation { + visibility: visible; + display: table; + background: #e2e2e2; + border: solid 1px #babdb6; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + height: 3em; + } +} + diff --git a/docs/libs/html/up-insensitive.png b/docs/libs/html/up-insensitive.png new file mode 100644 index 0000000..f404986 Binary files /dev/null and b/docs/libs/html/up-insensitive.png differ diff --git a/docs/libs/html/up.png b/docs/libs/html/up.png new file mode 100644 index 0000000..80b4b37 Binary files /dev/null and b/docs/libs/html/up.png differ diff --git a/docs/version.entities.in b/docs/version.entities.in new file mode 100644 index 0000000..286989f --- /dev/null +++ b/docs/version.entities.in @@ -0,0 +1,2 @@ + + diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..eb5ddb8 --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,14 @@ +noinst_PROGRAMS = test-video test-ogg test-mp4 test-readme \ + test-launch test-sdp test-uri test-auth \ + test-multicast test-multicast2 test-appsrc test-wfd + +#INCLUDES = -I$(top_srcdir) -I$(srcdir) + +AM_CFLAGS = $(GST_OBJ_CFLAGS) +LDADD = $(GST_OBJ_LIBS) $(GIO_LIBS) + +if HAVE_LIBCGROUP +noinst_PROGRAMS += test-cgroups +LDADD += $(LIBCGROUP_LIBS) +endif + diff --git a/examples/Makefile.in b/examples/Makefile.in new file mode 100644 index 0000000..82559a7 --- /dev/null +++ b/examples/Makefile.in @@ -0,0 +1,832 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = test-video$(EXEEXT) test-ogg$(EXEEXT) \ + test-mp4$(EXEEXT) test-readme$(EXEEXT) test-launch$(EXEEXT) \ + test-sdp$(EXEEXT) test-uri$(EXEEXT) test-auth$(EXEEXT) \ + test-multicast$(EXEEXT) test-multicast2$(EXEEXT) \ + test-appsrc$(EXEEXT) $(am__EXEEXT_1) +@HAVE_LIBCGROUP_TRUE@am__append_1 = test-cgroups +@HAVE_LIBCGROUP_TRUE@am__append_2 = $(LIBCGROUP_LIBS) +subdir = examples +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-docbook.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-default.m4 \ + $(top_srcdir)/common/m4/gst-doc.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@HAVE_LIBCGROUP_TRUE@am__EXEEXT_1 = test-cgroups$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +test_appsrc_SOURCES = test-appsrc.c +test_appsrc_OBJECTS = test-appsrc.$(OBJEXT) +test_appsrc_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +@HAVE_LIBCGROUP_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +test_appsrc_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +test_auth_SOURCES = test-auth.c +test_auth_OBJECTS = test-auth.$(OBJEXT) +test_auth_LDADD = $(LDADD) +test_auth_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +test_cgroups_SOURCES = test-cgroups.c +test_cgroups_OBJECTS = test-cgroups.$(OBJEXT) +test_cgroups_LDADD = $(LDADD) +test_cgroups_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) +test_launch_SOURCES = test-launch.c +test_launch_OBJECTS = test-launch.$(OBJEXT) +test_launch_LDADD = $(LDADD) +test_launch_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +test_mp4_SOURCES = test-mp4.c +test_mp4_OBJECTS = test-mp4.$(OBJEXT) +test_mp4_LDADD = $(LDADD) +test_mp4_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +test_multicast_SOURCES = test-multicast.c +test_multicast_OBJECTS = test-multicast.$(OBJEXT) +test_multicast_LDADD = $(LDADD) +test_multicast_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) +test_multicast2_SOURCES = test-multicast2.c +test_multicast2_OBJECTS = test-multicast2.$(OBJEXT) +test_multicast2_LDADD = $(LDADD) +test_multicast2_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) +test_ogg_SOURCES = test-ogg.c +test_ogg_OBJECTS = test-ogg.$(OBJEXT) +test_ogg_LDADD = $(LDADD) +test_ogg_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +test_readme_SOURCES = test-readme.c +test_readme_OBJECTS = test-readme.$(OBJEXT) +test_readme_LDADD = $(LDADD) +test_readme_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +test_sdp_SOURCES = test-sdp.c +test_sdp_OBJECTS = test-sdp.$(OBJEXT) +test_sdp_LDADD = $(LDADD) +test_sdp_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +test_uri_SOURCES = test-uri.c +test_uri_OBJECTS = test-uri.$(OBJEXT) +test_uri_LDADD = $(LDADD) +test_uri_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +test_video_SOURCES = test-video.c +test_video_OBJECTS = test-video.$(OBJEXT) +test_video_LDADD = $(LDADD) +test_video_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = test-appsrc.c test-auth.c test-cgroups.c test-launch.c \ + test-mp4.c test-multicast.c test-multicast2.c test-ogg.c \ + test-readme.c test-sdp.c test-uri.c test-video.c +DIST_SOURCES = test-appsrc.c test-auth.c test-cgroups.c test-launch.c \ + test-mp4.c test-multicast.c test-multicast2.c test-ogg.c \ + test-readme.c test-sdp.c test-uri.c test-video.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAT_ENTRY_END = @CAT_ENTRY_END@ +CAT_ENTRY_START = @CAT_ENTRY_START@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@ +DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@ +DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@ +DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@ +DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ = @GLIB_REQ@ +GREP = @GREP@ +GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@ +GSTPD_PLUGINS_DIR = @GSTPD_PLUGINS_DIR@ +GSTPG_PLUGINS_DIR = @GSTPG_PLUGINS_DIR@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_BASE_CFLAGS = @GST_BASE_CFLAGS@ +GST_BASE_LIBS = @GST_BASE_LIBS@ +GST_CFLAGS = @GST_CFLAGS@ +GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@ +GST_CHECK_LIBS = @GST_CHECK_LIBS@ +GST_CURRENT = @GST_CURRENT@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBS = @GST_LIBS@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGINS_BAD_CFLAGS = @GST_PLUGINS_BAD_CFLAGS@ +GST_PLUGINS_BAD_DIR = @GST_PLUGINS_BAD_DIR@ +GST_PLUGINS_BAD_LIBS = @GST_PLUGINS_BAD_LIBS@ +GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@ +GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@ +GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@ +GST_PLUGINS_DIR = @GST_PLUGINS_DIR@ +GST_PLUGINS_GOOD_CFLAGS = @GST_PLUGINS_GOOD_CFLAGS@ +GST_PLUGINS_GOOD_DIR = @GST_PLUGINS_GOOD_DIR@ +GST_PLUGINS_GOOD_LIBS = @GST_PLUGINS_GOOD_LIBS@ +GST_REVISION = @GST_REVISION@ +GST_TOOLS_DIR = @GST_TOOLS_DIR@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ +HAVE_DVIPS = @HAVE_DVIPS@ +HAVE_EPSTOPDF = @HAVE_EPSTOPDF@ +HAVE_JADETEX = @HAVE_JADETEX@ +HAVE_PNGTOPNM = @HAVE_PNGTOPNM@ +HAVE_PNMTOPS = @HAVE_PNMTOPS@ +HAVE_PS2PDF = @HAVE_PS2PDF@ +HAVE_XMLLINT = @HAVE_XMLLINT@ +HAVE_XSLTPROC = @HAVE_XSLTPROC@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCGROUP_CFLAGS = @LIBCGROUP_CFLAGS@ +LIBCGROUP_LIBS = @LIBCGROUP_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +XML_CATALOG = @XML_CATALOG@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +#INCLUDES = -I$(top_srcdir) -I$(srcdir) +AM_CFLAGS = $(GST_OBJ_CFLAGS) +LDADD = $(GST_OBJ_LIBS) $(GIO_LIBS) $(am__append_2) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu examples/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu examples/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-appsrc$(EXEEXT): $(test_appsrc_OBJECTS) $(test_appsrc_DEPENDENCIES) $(EXTRA_test_appsrc_DEPENDENCIES) + @rm -f test-appsrc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_appsrc_OBJECTS) $(test_appsrc_LDADD) $(LIBS) + +test-auth$(EXEEXT): $(test_auth_OBJECTS) $(test_auth_DEPENDENCIES) $(EXTRA_test_auth_DEPENDENCIES) + @rm -f test-auth$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_auth_OBJECTS) $(test_auth_LDADD) $(LIBS) + +test-cgroups$(EXEEXT): $(test_cgroups_OBJECTS) $(test_cgroups_DEPENDENCIES) $(EXTRA_test_cgroups_DEPENDENCIES) + @rm -f test-cgroups$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_cgroups_OBJECTS) $(test_cgroups_LDADD) $(LIBS) + +test-launch$(EXEEXT): $(test_launch_OBJECTS) $(test_launch_DEPENDENCIES) $(EXTRA_test_launch_DEPENDENCIES) + @rm -f test-launch$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_launch_OBJECTS) $(test_launch_LDADD) $(LIBS) + +test-mp4$(EXEEXT): $(test_mp4_OBJECTS) $(test_mp4_DEPENDENCIES) $(EXTRA_test_mp4_DEPENDENCIES) + @rm -f test-mp4$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_mp4_OBJECTS) $(test_mp4_LDADD) $(LIBS) + +test-multicast$(EXEEXT): $(test_multicast_OBJECTS) $(test_multicast_DEPENDENCIES) $(EXTRA_test_multicast_DEPENDENCIES) + @rm -f test-multicast$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_multicast_OBJECTS) $(test_multicast_LDADD) $(LIBS) + +test-multicast2$(EXEEXT): $(test_multicast2_OBJECTS) $(test_multicast2_DEPENDENCIES) $(EXTRA_test_multicast2_DEPENDENCIES) + @rm -f test-multicast2$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_multicast2_OBJECTS) $(test_multicast2_LDADD) $(LIBS) + +test-ogg$(EXEEXT): $(test_ogg_OBJECTS) $(test_ogg_DEPENDENCIES) $(EXTRA_test_ogg_DEPENDENCIES) + @rm -f test-ogg$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ogg_OBJECTS) $(test_ogg_LDADD) $(LIBS) + +test-readme$(EXEEXT): $(test_readme_OBJECTS) $(test_readme_DEPENDENCIES) $(EXTRA_test_readme_DEPENDENCIES) + @rm -f test-readme$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_readme_OBJECTS) $(test_readme_LDADD) $(LIBS) + +test-sdp$(EXEEXT): $(test_sdp_OBJECTS) $(test_sdp_DEPENDENCIES) $(EXTRA_test_sdp_DEPENDENCIES) + @rm -f test-sdp$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_sdp_OBJECTS) $(test_sdp_LDADD) $(LIBS) + +test-uri$(EXEEXT): $(test_uri_OBJECTS) $(test_uri_DEPENDENCIES) $(EXTRA_test_uri_DEPENDENCIES) + @rm -f test-uri$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_uri_OBJECTS) $(test_uri_LDADD) $(LIBS) + +test-video$(EXEEXT): $(test_video_OBJECTS) $(test_video_DEPENDENCIES) $(EXTRA_test_video_DEPENDENCIES) + @rm -f test-video$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_video_OBJECTS) $(test_video_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-appsrc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-auth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-cgroups.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-launch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-mp4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-multicast.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-multicast2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ogg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-readme.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-sdp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-uri.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-video.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/examples/test-appsrc.c b/examples/test-appsrc.c new file mode 100644 index 0000000..9d271ea --- /dev/null +++ b/examples/test-appsrc.c @@ -0,0 +1,137 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + +typedef struct +{ + gboolean white; + GstClockTime timestamp; +} MyContext; + +/* called when we need to give data to appsrc */ +static void +need_data (GstElement * appsrc, guint unused, MyContext * ctx) +{ + GstBuffer *buffer; + guint size; + GstFlowReturn ret; + + size = 385 * 288 * 2; + + buffer = gst_buffer_new_allocate (NULL, size, NULL); + + /* this makes the image black/white */ + gst_buffer_memset (buffer, 0, ctx->white ? 0xff : 0x0, size); + + ctx->white = !ctx->white; + + /* increment the timestamp every 1/2 second */ + GST_BUFFER_PTS (buffer) = ctx->timestamp; + GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND, 2); + ctx->timestamp += GST_BUFFER_DURATION (buffer); + + g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret); +} + +/* called when a new media pipeline is constructed. We can query the + * pipeline and configure our appsrc */ +static void +media_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media, + gpointer user_data) +{ + GstElement *element, *appsrc; + MyContext *ctx; + + /* get the element used for providing the streams of the media */ + element = gst_rtsp_media_get_element (media); + + /* get our appsrc, we named it 'mysrc' with the name property */ + appsrc = gst_bin_get_by_name_recurse_up (GST_BIN (element), "mysrc"); + + /* this instructs appsrc that we will be dealing with timed buffer */ + gst_util_set_object_arg (G_OBJECT (appsrc), "format", "time"); + /* configure the caps of the video */ + g_object_set (G_OBJECT (appsrc), "caps", + gst_caps_new_simple ("video/x-raw", + "format", G_TYPE_STRING, "RGB16", + "width", G_TYPE_INT, 384, + "height", G_TYPE_INT, 288, + "framerate", GST_TYPE_FRACTION, 0, 1, NULL), NULL); + + ctx = g_new0 (MyContext, 1); + ctx->white = FALSE; + ctx->timestamp = 0; + /* make sure ther datais freed when the media is gone */ + g_object_set_data_full (G_OBJECT (media), "my-extra-data", ctx, + (GDestroyNotify) g_free); + + /* install the callback that will be called when a buffer is needed */ + g_signal_connect (appsrc, "need-data", (GCallback) need_data, ctx); +} + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* get the mount points for this server, every server has a default object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + /* make a media factory for a test stream. The default media factory can use + * gst-launch syntax to create pipelines. + * any launch line works as long as it contains elements named pay%d. Each + * element with pay%d names will be a stream */ + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, + "( appsrc name=mysrc ! videoconvert ! x264enc ! rtph264pay name=pay0 pt=96 )"); + + /* notify when our media is ready, This is called whenever someone asks for + * the media and a new pipeline with our appsrc is created */ + g_signal_connect (factory, "media-configure", (GCallback) media_configure, + NULL); + + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + /* don't need the ref to the mounts anymore */ + g_object_unref (mounts); + + /* attach the server to the default maincontext */ + gst_rtsp_server_attach (server, NULL); + + /* start serving */ + g_print ("stream ready at rtsp://127.0.0.1:8554/test\n"); + g_main_loop_run (loop); + + return 0; +} diff --git a/examples/test-auth.c b/examples/test-auth.c new file mode 100644 index 0000000..eff3c74 --- /dev/null +++ b/examples/test-auth.c @@ -0,0 +1,186 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + +static gboolean +remove_func (GstRTSPSessionPool * pool, GstRTSPSession * session, + GstRTSPServer * server) +{ + return GST_RTSP_FILTER_REMOVE; +} + +static gboolean +remove_sessions (GstRTSPServer * server) +{ + GstRTSPSessionPool *pool; + + g_print ("removing all sessions\n"); + pool = gst_rtsp_server_get_session_pool (server); + gst_rtsp_session_pool_filter (pool, + (GstRTSPSessionPoolFilterFunc) remove_func, server); + g_object_unref (pool); + + return FALSE; +} + +static gboolean +timeout (GstRTSPServer * server) +{ + GstRTSPSessionPool *pool; + + pool = gst_rtsp_server_get_session_pool (server); + gst_rtsp_session_pool_cleanup (pool); + g_object_unref (pool); + + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + GstRTSPAuth *auth; + GstRTSPToken *token; + gchar *basic; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* get the mounts for this server, every server has a default mapper object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + + /* make a media factory for a test stream. The default media factory can use + * gst-launch syntax to create pipelines. + * any launch line works as long as it contains elements named pay%d. Each + * element with pay%d names will be a stream */ + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, "( " + "videotestsrc ! video/x-raw,width=352,height=288,framerate=15/1 ! " + "x264enc ! rtph264pay name=pay0 pt=96 " + "audiotestsrc ! audio/x-raw,rate=8000 ! " + "alawenc ! rtppcmapay name=pay1 pt=97 " ")"); + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + /* allow user and admin to access this resource */ + gst_rtsp_media_factory_add_role (factory, "user", + GST_RTSP_PERM_MEDIA_FACTORY_ACCESS, G_TYPE_BOOLEAN, TRUE, + GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT, G_TYPE_BOOLEAN, TRUE, NULL); + gst_rtsp_media_factory_add_role (factory, "admin", + GST_RTSP_PERM_MEDIA_FACTORY_ACCESS, G_TYPE_BOOLEAN, TRUE, + GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT, G_TYPE_BOOLEAN, TRUE, NULL); + /* admin2 can look at the media but not construct so he gets a + * 401 Unauthorized */ + gst_rtsp_media_factory_add_role (factory, "admin2", + GST_RTSP_PERM_MEDIA_FACTORY_ACCESS, G_TYPE_BOOLEAN, TRUE, + GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT, G_TYPE_BOOLEAN, FALSE, NULL); + + /* make another factory */ + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, "( " + "videotestsrc ! video/x-raw,width=352,height=288,framerate=30/1 ! " + "x264enc ! rtph264pay name=pay0 pt=96 )"); + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test2", factory); + + /* allow admin2 to access this resource */ + /* user and admin have no permissions so they can't even see the + * media and get a 404 Not Found */ + gst_rtsp_media_factory_add_role (factory, "admin2", + GST_RTSP_PERM_MEDIA_FACTORY_ACCESS, G_TYPE_BOOLEAN, TRUE, + GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT, G_TYPE_BOOLEAN, TRUE, NULL); + + /* don't need the ref to the mapper anymore */ + g_object_unref (mounts); + + /* make a new authentication manager */ + auth = gst_rtsp_auth_new (); + + /* make default token, it has the same permissions as admin2 */ + token = + gst_rtsp_token_new (GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING, + "admin2", NULL); + gst_rtsp_auth_set_default_token (auth, token); + gst_rtsp_token_unref (token); + + /* make user token */ + token = + gst_rtsp_token_new (GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING, + "user", NULL); + basic = gst_rtsp_auth_make_basic ("user", "password"); + gst_rtsp_auth_add_basic (auth, basic, token); + g_free (basic); + gst_rtsp_token_unref (token); + + /* make admin token */ + token = + gst_rtsp_token_new (GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING, + "admin", NULL); + basic = gst_rtsp_auth_make_basic ("admin", "power"); + gst_rtsp_auth_add_basic (auth, basic, token); + g_free (basic); + gst_rtsp_token_unref (token); + + /* make admin2 token */ + token = + gst_rtsp_token_new (GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING, + "admin2", NULL); + basic = gst_rtsp_auth_make_basic ("admin2", "power2"); + gst_rtsp_auth_add_basic (auth, basic, token); + g_free (basic); + gst_rtsp_token_unref (token); + + /* set as the server authentication manager */ + gst_rtsp_server_set_auth (server, auth); + g_object_unref (auth); + + /* attach the server to the default maincontext */ + if (gst_rtsp_server_attach (server, NULL) == 0) + goto failed; + + g_timeout_add_seconds (2, (GSourceFunc) timeout, server); + g_timeout_add_seconds (10, (GSourceFunc) remove_sessions, server); + + /* start serving */ + g_print ("stream with user:password ready at rtsp://127.0.0.1:8554/test\n"); + g_print ("stream with admin:power ready at rtsp://127.0.0.1:8554/test\n"); + g_print ("stream with admin2:power2 ready at rtsp://127.0.0.1:8554/test2\n"); + g_main_loop_run (loop); + + return 0; + + /* ERRORS */ +failed: + { + g_print ("failed to attach the server\n"); + return -1; + } +} diff --git a/examples/test-cgroups.c b/examples/test-cgroups.c new file mode 100644 index 0000000..600fa3c --- /dev/null +++ b/examples/test-cgroups.c @@ -0,0 +1,276 @@ +/* GStreamer + * Copyright (C) 2013 Wim Taymans + * + * 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. + */ + +/* Runs a pipeline and clasifies the media pipelines based on the + * authenticated user. + * + * This test requires 2 cpu cgroups to exist named 'user' and 'admin'. + * The rtsp server should have permission to add its threads to the + * cgroups. + * + * sudo cgcreate -t uid:gid -g cpu:/user + * sudo cgcreate -t uid:gid -g cpu:/admin + * + * With -t you can give the user and group access to the task file to + * write the thread ids. The user running the server can be used. + * + * Then you would want to change the cpu shares assigned to each group: + * + * sudo cgset -r cpu.shares=100 user + * sudo cgset -r cpu.shares=1024 admin + * + * Then start clients for 'user' until the stream is degraded because of + * lack of CPU. Then start a client for 'admin' and check that the stream + * is not degraded. + */ + +#include + +#include +#include + +typedef struct _GstRTSPCGroupPool GstRTSPCGroupPool; +typedef struct _GstRTSPCGroupPoolClass GstRTSPCGroupPoolClass; + +#define GST_TYPE_RTSP_CGROUP_POOL (gst_rtsp_cgroup_pool_get_type ()) +#define GST_IS_RTSP_CGROUP_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_CGROUP_POOL)) +#define GST_IS_RTSP_CGROUP_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_CGROUP_POOL)) +#define GST_RTSP_CGROUP_POOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_CGROUP_POOL, GstRTSPCGroupPoolClass)) +#define GST_RTSP_CGROUP_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_CGROUP_POOL, GstRTSPCGroupPool)) +#define GST_RTSP_CGROUP_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_CGROUP_POOL, GstRTSPCGroupPoolClass)) +#define GST_RTSP_CGROUP_POOL_CAST(obj) ((GstRTSPCGroupPool*)(obj)) +#define GST_RTSP_CGROUP_POOL_CLASS_CAST(klass) ((GstRTSPCGroupPoolClass*)(klass)) + +struct _GstRTSPCGroupPool +{ + GstRTSPThreadPool parent; + + struct cgroup *user; + struct cgroup *admin; +}; + +struct _GstRTSPCGroupPoolClass +{ + GstRTSPThreadPoolClass parent_class; +}; + +static GQuark thread_cgroup; + +static void gst_rtsp_cgroup_pool_finalize (GObject * obj); + +static void default_thread_enter (GstRTSPThreadPool * pool, + GstRTSPThread * thread); +static void default_configure_thread (GstRTSPThreadPool * pool, + GstRTSPThread * thread, GstRTSPContext * ctx); + +static GType gst_rtsp_cgroup_pool_get_type (void); + +G_DEFINE_TYPE (GstRTSPCGroupPool, gst_rtsp_cgroup_pool, + GST_TYPE_RTSP_THREAD_POOL); + +static void +gst_rtsp_cgroup_pool_class_init (GstRTSPCGroupPoolClass * klass) +{ + GObjectClass *gobject_class; + GstRTSPThreadPoolClass *tpool_class; + + gobject_class = G_OBJECT_CLASS (klass); + tpool_class = GST_RTSP_THREAD_POOL_CLASS (klass); + + gobject_class->finalize = gst_rtsp_cgroup_pool_finalize; + + tpool_class->configure_thread = default_configure_thread; + tpool_class->thread_enter = default_thread_enter; + + thread_cgroup = g_quark_from_string ("cgroup.pool.thread.cgroup"); + + cgroup_init (); +} + +static void +gst_rtsp_cgroup_pool_init (GstRTSPCGroupPool * pool) +{ + pool->user = cgroup_new_cgroup ("user"); + if (cgroup_add_controller (pool->user, "cpu") == NULL) + g_error ("Failed to add cpu controller to user cgroup"); + pool->admin = cgroup_new_cgroup ("admin"); + if (cgroup_add_controller (pool->admin, "cpu") == NULL) + g_error ("Failed to add cpu controller to admin cgroup"); +} + +static void +gst_rtsp_cgroup_pool_finalize (GObject * obj) +{ + GstRTSPCGroupPool *pool = GST_RTSP_CGROUP_POOL (obj); + + GST_INFO ("finalize pool %p", pool); + + cgroup_free (&pool->user); + cgroup_free (&pool->admin); + + G_OBJECT_CLASS (gst_rtsp_cgroup_pool_parent_class)->finalize (obj); +} + +static void +default_thread_enter (GstRTSPThreadPool * pool, GstRTSPThread * thread) +{ + struct cgroup *cgroup; + + cgroup = gst_mini_object_get_qdata (GST_MINI_OBJECT (thread), thread_cgroup); + if (cgroup) { + gint res = 0; + + res = cgroup_attach_task (cgroup); + + if (res != 0) + GST_ERROR ("error: %d (%s)", res, cgroup_strerror (res)); + } +} + +static void +default_configure_thread (GstRTSPThreadPool * pool, + GstRTSPThread * thread, GstRTSPContext * ctx) +{ + GstRTSPCGroupPool *cpool = GST_RTSP_CGROUP_POOL (pool); + const gchar *cls; + struct cgroup *cgroup; + + if (ctx->token) + cls = gst_rtsp_token_get_string (ctx->token, "cgroup.pool.media.class"); + else + cls = NULL; + + GST_DEBUG ("manage cgroup %s", cls); + + if (!g_strcmp0 (cls, "admin")) + cgroup = cpool->admin; + else + cgroup = cpool->user; + + /* attach the cgroup to the thread */ + gst_mini_object_set_qdata (GST_MINI_OBJECT (thread), thread_cgroup, + cgroup, NULL); +} + +static gboolean +timeout (GstRTSPServer * server) +{ + GstRTSPSessionPool *pool; + + pool = gst_rtsp_server_get_session_pool (server); + gst_rtsp_session_pool_cleanup (pool); + g_object_unref (pool); + + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + GstRTSPAuth *auth; + GstRTSPToken *token; + gchar *basic; + GstRTSPThreadPool *thread_pool; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* get the mounts for this server, every server has a default mapper object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + /* make a media factory for a test stream. The default media factory can use + * gst-launch syntax to create pipelines. + * any launch line works as long as it contains elements named pay%d. Each + * element with pay%d names will be a stream */ + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, "( " + "videotestsrc ! video/x-raw,width=640,height=480,framerate=50/1 ! " + "x264enc ! rtph264pay name=pay0 pt=96 " + "audiotestsrc ! audio/x-raw,rate=8000 ! " + "alawenc ! rtppcmapay name=pay1 pt=97 " ")"); + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + /* allow user and admin to access this resource */ + gst_rtsp_media_factory_add_role (factory, "user", + "media.factory.access", G_TYPE_BOOLEAN, TRUE, + "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL); + gst_rtsp_media_factory_add_role (factory, "admin", + "media.factory.access", G_TYPE_BOOLEAN, TRUE, + "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL); + + /* don't need the ref to the mapper anymore */ + g_object_unref (mounts); + + /* make a new authentication manager */ + auth = gst_rtsp_auth_new (); + + /* make user token */ + token = gst_rtsp_token_new ("cgroup.pool.media.class", G_TYPE_STRING, "user", + "media.factory.role", G_TYPE_STRING, "user", NULL); + basic = gst_rtsp_auth_make_basic ("user", "password"); + gst_rtsp_auth_add_basic (auth, basic, token); + g_free (basic); + gst_rtsp_token_unref (token); + + /* make admin token */ + token = gst_rtsp_token_new ("cgroup.pool.media.class", G_TYPE_STRING, "admin", + "media.factory.role", G_TYPE_STRING, "admin", NULL); + basic = gst_rtsp_auth_make_basic ("admin", "power"); + gst_rtsp_auth_add_basic (auth, basic, token); + g_free (basic); + gst_rtsp_token_unref (token); + + /* set as the server authentication manager */ + gst_rtsp_server_set_auth (server, auth); + g_object_unref (auth); + + thread_pool = g_object_new (GST_TYPE_RTSP_CGROUP_POOL, NULL); + gst_rtsp_server_set_thread_pool (server, thread_pool); + g_object_unref (thread_pool); + + /* attach the server to the default maincontext */ + if (gst_rtsp_server_attach (server, NULL) == 0) + goto failed; + + g_timeout_add_seconds (2, (GSourceFunc) timeout, server); + + /* start serving */ + g_print ("stream with user:password ready at rtsp://127.0.0.1:8554/test\n"); + g_print ("stream with admin:power ready at rtsp://127.0.0.1:8554/test\n"); + g_main_loop_run (loop); + + return 0; + + /* ERRORS */ +failed: + { + g_print ("failed to attach the server\n"); + return -1; + } +} diff --git a/examples/test-launch.c b/examples/test-launch.c new file mode 100644 index 0000000..0466224 --- /dev/null +++ b/examples/test-launch.c @@ -0,0 +1,71 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + + gst_init (&argc, &argv); + + if (argc < 2) { + g_print ("usage: %s \n" + "example: %s \"( videotestsrc ! x264enc ! rtph264pay name=pay0 pt=96 )\"\n", + argv[0], argv[0]); + return -1; + } + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* get the mount points for this server, every server has a default object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + /* make a media factory for a test stream. The default media factory can use + * gst-launch syntax to create pipelines. + * any launch line works as long as it contains elements named pay%d. Each + * element with pay%d names will be a stream */ + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, argv[1]); + + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + /* don't need the ref to the mapper anymore */ + g_object_unref (mounts); + + /* attach the server to the default maincontext */ + gst_rtsp_server_attach (server, NULL); + + /* start serving */ + g_print ("stream ready at rtsp://127.0.0.1:8554/test\n"); + g_main_loop_run (loop); + + return 0; +} diff --git a/examples/test-mp4.c b/examples/test-mp4.c new file mode 100644 index 0000000..52e082d --- /dev/null +++ b/examples/test-mp4.c @@ -0,0 +1,76 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + gchar *str; + + gst_init (&argc, &argv); + + if (argc < 2) { + g_message ("usage: %s ", argv[0]); + return -1; + } + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* get the mount points for this server, every server has a default object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + str = g_strdup_printf ("( " + "filesrc location=%s ! qtdemux name=d " + "d. ! queue ! rtph264pay pt=96 name=pay0 " + "d. ! queue ! rtpmp4apay pt=97 name=pay1 " ")", argv[1]); + + /* make a media factory for a test stream. The default media factory can use + * gst-launch syntax to create pipelines. + * any launch line works as long as it contains elements named pay%d. Each + * element with pay%d names will be a stream */ + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, str); + g_free (str); + + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + /* don't need the ref to the mapper anymore */ + g_object_unref (mounts); + + /* attach the server to the default maincontext */ + gst_rtsp_server_attach (server, NULL); + + /* start serving */ + g_print ("stream ready at rtsp://127.0.0.1:8554/test\n"); + g_main_loop_run (loop); + + return 0; +} diff --git a/examples/test-multicast.c b/examples/test-multicast.c new file mode 100644 index 0000000..c7d55fc --- /dev/null +++ b/examples/test-multicast.c @@ -0,0 +1,104 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + + +static gboolean +timeout (GstRTSPServer * server, gboolean ignored) +{ + GstRTSPSessionPool *pool; + + pool = gst_rtsp_server_get_session_pool (server); + gst_rtsp_session_pool_cleanup (pool); + g_object_unref (pool); + + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + GstRTSPAddressPool *pool; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* get the mount points for this server, every server has a default object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + /* make a media factory for a test stream. The default media factory can use + * gst-launch syntax to create pipelines. + * any launch line works as long as it contains elements named pay%d. Each + * element with pay%d names will be a stream */ + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, "( " + "videotestsrc ! video/x-raw,width=352,height=288,framerate=15/1 ! " + "x264enc ! rtph264pay name=pay0 pt=96 " + "audiotestsrc ! audio/x-raw,rate=8000 ! " + "alawenc ! rtppcmapay name=pay1 pt=97 " ")"); + + gst_rtsp_media_factory_set_shared (factory, TRUE); + + /* make a new address pool */ + pool = gst_rtsp_address_pool_new (); + gst_rtsp_address_pool_add_range (pool, + "224.3.0.0", "224.3.0.10", 5000, 5010, 16); + gst_rtsp_media_factory_set_address_pool (factory, pool); + /* only allow multicast */ + gst_rtsp_media_factory_set_protocols (factory, + GST_RTSP_LOWER_TRANS_UDP_MCAST); + g_object_unref (pool); + + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + /* don't need the ref to the mapper anymore */ + g_object_unref (mounts); + + /* attach the server to the default maincontext */ + if (gst_rtsp_server_attach (server, NULL) == 0) + goto failed; + + g_timeout_add_seconds (2, (GSourceFunc) timeout, server); + + /* start serving */ + g_print ("stream ready at rtsp://127.0.0.1:8554/test\n"); + g_main_loop_run (loop); + + return 0; + + /* ERRORS */ +failed: + { + g_print ("failed to attach the server\n"); + return -1; + } +} diff --git a/examples/test-multicast2.c b/examples/test-multicast2.c new file mode 100644 index 0000000..1d8e6f2 --- /dev/null +++ b/examples/test-multicast2.c @@ -0,0 +1,125 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + + +static gboolean +timeout (GstRTSPServer * server, gboolean ignored) +{ + GstRTSPSessionPool *pool; + + pool = gst_rtsp_server_get_session_pool (server); + gst_rtsp_session_pool_cleanup (pool); + g_object_unref (pool); + + return TRUE; +} + +static void +media_constructed (GstRTSPMediaFactory * factory, GstRTSPMedia * media) +{ + guint i, n_streams; + + n_streams = gst_rtsp_media_n_streams (media); + + for (i = 0; i < n_streams; i++) { + GstRTSPAddressPool *pool; + GstRTSPStream *stream; + gchar *min, *max; + + stream = gst_rtsp_media_get_stream (media, i); + + /* make a new address pool */ + pool = gst_rtsp_address_pool_new (); + + min = g_strdup_printf ("224.3.0.%d", (2 * i) + 1); + max = g_strdup_printf ("224.3.0.%d", (2 * i) + 2); + gst_rtsp_address_pool_add_range (pool, min, max, + 5000 + (10 * i), 5010 + (10 * i), 1); + g_free (min); + g_free (max); + + gst_rtsp_stream_set_address_pool (stream, pool); + g_object_unref (pool); + } +} + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* get the mount points for this server, every server has a default object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + /* make a media factory for a test stream. The default media factory can use + * gst-launch syntax to create pipelines. + * any launch line works as long as it contains elements named pay%d. Each + * element with pay%d names will be a stream */ + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, "( " + "videotestsrc ! video/x-raw,width=352,height=288,framerate=15/1 ! " + "x264enc ! rtph264pay name=pay0 pt=96 " + "audiotestsrc ! audio/x-raw,rate=8000 ! " + "alawenc ! rtppcmapay name=pay1 pt=97 " ")"); + + gst_rtsp_media_factory_set_shared (factory, TRUE); + + g_signal_connect (factory, "media-constructed", (GCallback) + media_constructed, NULL); + + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + /* don't need the ref to the mapper anymore */ + g_object_unref (mounts); + + /* attach the server to the default maincontext */ + if (gst_rtsp_server_attach (server, NULL) == 0) + goto failed; + + g_timeout_add_seconds (2, (GSourceFunc) timeout, server); + + /* start serving */ + g_print ("stream ready at rtsp://127.0.0.1:8554/test\n"); + g_main_loop_run (loop); + + return 0; + + /* ERRORS */ +failed: + { + g_print ("failed to attach the server\n"); + return -1; + } +} diff --git a/examples/test-ogg.c b/examples/test-ogg.c new file mode 100644 index 0000000..f4d104c --- /dev/null +++ b/examples/test-ogg.c @@ -0,0 +1,76 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + gchar *str; + + gst_init (&argc, &argv); + + if (argc < 2) { + g_message ("usage: %s ", argv[0]); + return -1; + } + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* get the mount points for this server, every server has a default object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + str = g_strdup_printf ("( " + "filesrc location=%s ! oggdemux name=d " + "d. ! queue ! rtptheorapay name=pay0 pt=96 " + "d. ! queue ! rtpvorbispay name=pay1 pt=97 " ")", argv[1]); + + /* make a media factory for a test stream. The default media factory can use + * gst-launch syntax to create pipelines. + * any launch line works as long as it contains elements named pay%d. Each + * element with pay%d names will be a stream */ + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, str); + g_free (str); + + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + /* don't need the ref to the mapper anymore */ + g_object_unref (mounts); + + /* attach the server to the default maincontext */ + gst_rtsp_server_attach (server, NULL); + + /* start serving */ + g_print ("stream ready at rtsp://127.0.0.1:8554/test\n"); + g_main_loop_run (loop); + + return 0; +} diff --git a/examples/test-readme.c b/examples/test-readme.c new file mode 100644 index 0000000..2e2caa6 --- /dev/null +++ b/examples/test-readme.c @@ -0,0 +1,67 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* get the mount points for this server, every server has a default object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + /* make a media factory for a test stream. The default media factory can use + * gst-launch syntax to create pipelines. + * any launch line works as long as it contains elements named pay%d. Each + * element with pay%d names will be a stream */ + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc is-live=1 ! x264enc ! rtph264pay name=pay0 pt=96 )"); + + gst_rtsp_media_factory_set_shared (factory, TRUE); + + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + /* don't need the ref to the mapper anymore */ + g_object_unref (mounts); + + /* attach the server to the default maincontext */ + gst_rtsp_server_attach (server, NULL); + + /* start serving */ + g_print ("stream ready at rtsp://127.0.0.1:8554/test\n"); + g_main_loop_run (loop); + + return 0; +} diff --git a/examples/test-sdp.c b/examples/test-sdp.c new file mode 100644 index 0000000..98efe9e --- /dev/null +++ b/examples/test-sdp.c @@ -0,0 +1,98 @@ +/* GStreamer + * Copyright (C) 2009 Wim Taymans + * + * 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. + */ + +#include + +#include + + +static gboolean +timeout (GstRTSPServer * server, gboolean ignored) +{ + GstRTSPSessionPool *pool; + + pool = gst_rtsp_server_get_session_pool (server); + gst_rtsp_session_pool_cleanup (pool); + g_object_unref (pool); + + return TRUE; +} + +static void +media_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media) +{ + gst_rtsp_media_set_reusable (media, TRUE); +} + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + gchar *str; + + gst_init (&argc, &argv); + + if (argc < 2) { + g_message ("usage: %s ", argv[0]); + return -1; + } + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* get the mount points for this server, every server has a default object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + /* make a media factory for a test stream. The default media factory can use + * gst-launch syntax to create pipelines. + * any launch line works as long as it contains elements named pay%d. Each + * element with pay%d names will be a stream */ + factory = gst_rtsp_media_factory_new (); + + str = + g_strdup_printf ("( filesrc location=%s ! sdpdemux name=dynpay0 )", + argv[1]); + gst_rtsp_media_factory_set_launch (factory, str); + gst_rtsp_media_factory_set_shared (factory, TRUE); + g_signal_connect (factory, "media-configure", (GCallback) media_configure, + NULL); + g_free (str); + + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + /* don't need the ref to the mapper anymore */ + g_object_unref (mounts); + + /* attach the server to the default maincontext */ + gst_rtsp_server_attach (server, NULL); + + g_timeout_add_seconds (2, (GSourceFunc) timeout, server); + + /* start serving */ + g_main_loop_run (loop); + + return 0; +} diff --git a/examples/test-uri.c b/examples/test-uri.c new file mode 100644 index 0000000..b0daebc --- /dev/null +++ b/examples/test-uri.c @@ -0,0 +1,114 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include +#include + + +static gboolean +timeout (GstRTSPServer * server) +{ + GstRTSPSessionPool *pool; + + pool = gst_rtsp_server_get_session_pool (server); + gst_rtsp_session_pool_cleanup (pool); + g_object_unref (pool); + + return TRUE; +} + +static gboolean +remove_map (GstRTSPServer * server) +{ + GstRTSPMountPoints *mounts; + + g_print ("removing /test mount point\n"); + mounts = gst_rtsp_server_get_mount_points (server); + gst_rtsp_mount_points_remove_factory (mounts, "/test"); + g_object_unref (mounts); + + return FALSE; +} + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactoryURI *factory; + + gst_init (&argc, &argv); + + if (argc < 2) { + g_message ("usage: %s ", argv[0]); + return -1; + } + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* get the mount points for this server, every server has a default object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + /* make a URI media factory for a test stream. */ + factory = gst_rtsp_media_factory_uri_new (); + /* when using GStreamer as a client, one can use the gst payloader, which is + * more efficient when there is no payloader for the compressed format */ + /* g_object_set (factory, "use-gstpay", TRUE, NULL); */ + gst_rtsp_media_factory_uri_set_uri (factory, argv[1]); + /* if you want multiple clients to see the same video, set the shared property + * to TRUE */ + /* gst_rtsp_media_factory_set_shared ( GST_RTSP_MEDIA_FACTORY (factory), TRUE); */ + + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", + GST_RTSP_MEDIA_FACTORY (factory)); + + /* don't need the ref to the mapper anymore */ + g_object_unref (mounts); + + /* attach the server to the default maincontext */ + if (gst_rtsp_server_attach (server, NULL) == 0) + goto failed; + + /* do session cleanup every 2 seconds */ + g_timeout_add_seconds (2, (GSourceFunc) timeout, server); + /* remove the mount point after 10 seconds, new clients won't be able to use the + * /test url anymore */ + g_timeout_add_seconds (10, (GSourceFunc) remove_map, server); + + /* start serving */ + g_print ("stream ready at rtsp://127.0.0.1:8554/test\n"); + g_main_loop_run (loop); + + return 0; + + /* ERRORS */ +failed: + { + g_print ("failed to attach the server\n"); + return -1; + } +} diff --git a/examples/test-video.c b/examples/test-video.c new file mode 100644 index 0000000..0d4a3a5 --- /dev/null +++ b/examples/test-video.c @@ -0,0 +1,177 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + +/* define this if you want the resource to only be available when using + * user/password as the password */ +#undef WITH_AUTH + +/* define this if you want the server to use TLS (it will also need WITH_AUTH + * to be defined) */ +#undef WITH_TLS + +/* this timeout is periodically run to clean up the expired sessions from the + * pool. This needs to be run explicitly currently but might be done + * automatically as part of the mainloop. */ +static gboolean +timeout (GstRTSPServer * server, gboolean ignored) +{ + GstRTSPSessionPool *pool; + + pool = gst_rtsp_server_get_session_pool (server); + gst_rtsp_session_pool_cleanup (pool); + g_object_unref (pool); + + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; +#ifdef WITH_AUTH + GstRTSPAuth *auth; + GstRTSPToken *token; + gchar *basic; + GstRTSPPermissions *permissions; +#endif +#ifdef WITH_TLS + GTlsCertificate *cert; + GError *error = NULL; +#endif + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + +#ifdef WITH_AUTH + /* make a new authentication manager. it can be added to control access to all + * the factories on the server or on individual factories. */ + auth = gst_rtsp_auth_new (); +#ifdef WITH_TLS + cert = g_tls_certificate_new_from_pem ("-----BEGIN CERTIFICATE-----" + "MIICJjCCAY+gAwIBAgIBBzANBgkqhkiG9w0BAQUFADCBhjETMBEGCgmSJomT8ixk" + "ARkWA0NPTTEXMBUGCgmSJomT8ixkARkWB0VYQU1QTEUxHjAcBgNVBAsTFUNlcnRp" + "ZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAxMOY2EuZXhhbXBsZS5jb20xHTAbBgkq" + "hkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tMB4XDTExMDExNzE5NDcxN1oXDTIxMDEx" + "NDE5NDcxN1owSzETMBEGCgmSJomT8ixkARkWA0NPTTEXMBUGCgmSJomT8ixkARkW" + "B0VYQU1QTEUxGzAZBgNVBAMTEnNlcnZlci5leGFtcGxlLmNvbTBcMA0GCSqGSIb3" + "DQEBAQUAA0sAMEgCQQDYScTxk55XBmbDM9zzwO+grVySE4rudWuzH2PpObIonqbf" + "hRoAalKVluG9jvbHI81eXxCdSObv1KBP1sbN5RzpAgMBAAGjIjAgMAkGA1UdEwQC" + "MAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQEFBQADgYEAYx6fMqT1" + "Gvo0jq88E8mc+bmp4LfXD4wJ7KxYeadQxt75HFRpj4FhFO3DOpVRFgzHlOEo3Fwk" + "PZOKjvkT0cbcoEq5whLH25dHoQxGoVQgFyAP5s+7Vp5AlHh8Y/vAoXeEVyy/RCIH" + "QkhUlAflfDMcrrYjsmwoOPSjhx6Mm/AopX4=" + "-----END CERTIFICATE-----" + "-----BEGIN PRIVATE KEY-----" + "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA2EnE8ZOeVwZmwzPc" + "88DvoK1ckhOK7nVrsx9j6TmyKJ6m34UaAGpSlZbhvY72xyPNXl8QnUjm79SgT9bG" + "zeUc6QIDAQABAkBRFJZ32VbqWMP9OVwDJLiwC01AlYLnka0mIQZbT/2xq9dUc9GW" + "U3kiVw4lL8v/+sPjtTPCYYdzHHOyDen6znVhAiEA9qJT7BtQvRxCvGrAhr9MS022" + "tTdPbW829BoUtIeH64cCIQDggG5i48v7HPacPBIH1RaSVhXl8qHCpQD3qrIw3FMw" + "DwIga8PqH5Sf5sHedy2+CiK0V4MRfoU4c3zQ6kArI+bEgSkCIQCLA1vXBiE31B5s" + "bdHoYa1BXebfZVd+1Hd95IfEM5mbRwIgSkDuQwV55BBlvWph3U8wVIMIb4GStaH8" + "W535W8UBbEg=" "-----END PRIVATE KEY-----", -1, &error); + if (cert == NULL) { + g_printerr ("failed to parse PEM: %s\n", error->message); + return -1; + } + gst_rtsp_auth_set_tls_certificate (auth, cert); + g_object_unref (cert); +#endif + + /* make user token */ + token = + gst_rtsp_token_new (GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING, + "user", NULL); + basic = gst_rtsp_auth_make_basic ("user", "password"); + gst_rtsp_auth_add_basic (auth, basic, token); + g_free (basic); + gst_rtsp_token_unref (token); + + /* configure in the server */ + gst_rtsp_server_set_auth (server, auth); +#endif + + /* get the mount points for this server, every server has a default object + * that be used to map uri mount points to media factories */ + mounts = gst_rtsp_server_get_mount_points (server); + + /* make a media factory for a test stream. The default media factory can use + * gst-launch syntax to create pipelines. + * any launch line works as long as it contains elements named pay%d. Each + * element with pay%d names will be a stream */ + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, "( " + "videotestsrc ! video/x-raw,width=352,height=288,framerate=15/1 ! " + "x264enc ! rtph264pay name=pay0 pt=96 " + "audiotestsrc ! audio/x-raw,rate=8000 ! " + "alawenc ! rtppcmapay name=pay1 pt=97 " ")"); +#ifdef WITH_AUTH + /* add permissions for the user media role */ + permissions = gst_rtsp_permissions_new (); + gst_rtsp_permissions_add_role (permissions, "user", + GST_RTSP_PERM_MEDIA_FACTORY_ACCESS, G_TYPE_BOOLEAN, TRUE, + GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT, G_TYPE_BOOLEAN, TRUE, NULL); + gst_rtsp_media_factory_set_permissions (factory, permissions); + gst_rtsp_permissions_unref (permissions); +#ifdef WITH_TLS + gst_rtsp_media_factory_set_profiles (factory, GST_RTSP_PROFILE_SAVP); +#endif +#endif + + /* attach the test factory to the /test url */ + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + /* don't need the ref to the mapper anymore */ + g_object_unref (mounts); + + /* attach the server to the default maincontext */ + if (gst_rtsp_server_attach (server, NULL) == 0) + goto failed; + + /* add a timeout for the session cleanup */ + g_timeout_add_seconds (2, (GSourceFunc) timeout, server); + + /* start serving, this never stops */ +#ifdef WITH_TLS + g_print ("stream ready at rtsps://127.0.0.1:8554/test\n"); +#else + g_print ("stream ready at rtsp://127.0.0.1:8554/test\n"); +#endif + g_main_loop_run (loop); + + return 0; + + /* ERRORS */ +failed: + { + g_print ("failed to attach the server\n"); + return -1; + } +} diff --git a/examples/test-wfd.c b/examples/test-wfd.c new file mode 100644 index 0000000..26af281 --- /dev/null +++ b/examples/test-wfd.c @@ -0,0 +1,133 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include +#include + +#include +#include + +#if 1 +#define VIDEO_PIPELINE "ximagesrc ! videorate ! videoscale ! videoconvert ! " \ + "video/x-raw,width=640,height=480,framerate=30/1 ! " \ + "x264enc aud=false byte-stream=true bitrate=512 ! video/x-h264,profile=baseline ! mpegtsmux wfd-mode=TRUE ! " \ + "rtpmp2tpay name=pay0 pt=33" +#define AUDIO_PIPELINE "pulsesrc device=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor ! audioconvert ! " \ + "faac ! mpegtsmux wfd-mode=TRUE ! " \ + "rtpmp2tpay name=pay0 pt=33" +#else +#define VIDEO_PIPELINE "ximagesrc ! videoscale ! videoconvert ! " \ + "video/x-raw,width=640,height=480,framerate=60/1 ! " \ + "x264enc aud=false byte-stream=true bitrate=512 ! video/x-h264,profile=baseline ! mpegtsmux name=mux " \ + "pulsesrc device=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor ! audioconvert ! " \ + "faac ! mux. mux. ! " \ + "rtpmp2tpay name=pay0 pt=33" +#if 0 +#define VIDEO_PIPELINE "ximagesrc startx=0 starty=0 endx=1919 endy=1079 ! videorate ! videoscale ! video/x-raw,width=1280,height=720,framerate=30/1 ! videoconvert ! " \ + "x264enc aud=false byte-stream=true bitrate=512 ! video/x-h264,profile=baseline ! mpegtsmux name=mux wfd-mode=TRUE " \ + "pulsesrc device=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor ! audioconvert ! " \ + "faac ! mux. mux. ! " \ + "rtpmp2tpay name=pay0 pt=33" +#endif +/* +#define VIDEO_PIPELINE "ximagesrc do-timestamp=true ! videoscale ! video/x-raw,width=1280,height=720,framerate=30/1 ! videoconvert ! " \ + "x264enc aud=false byte-stream=true bitrate=512 ! video/x-h264,profile=baseline ! mpegtsmux name=mux wfd-mode=TRUE " \ + "pulsesrc device=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor provide-clock=false ! audioconvert ! " \ + "faac ! mux. mux. ! " \ + "rtpmp2tpay name=pay0 pt=33" +*/ +#endif + +#define WFD_RTSP_PORT "2022" +#define TEST_MOUNT_POINT "/wfd1.0/streamid=0" + +GMainLoop *loop; + +static gboolean +teardown(gpointer data) +{ + GstRTSPWFDServer *server = NULL; + server = (GstRTSPWFDServer *) data; + + g_print("teardown\n"); + + if (server == NULL) return FALSE; + + gst_rtsp_wfd_server_trigger_request (GST_RTSP_SERVER(server), WFD_TRIGGER_TEARDOWN); + + return FALSE; +} + +int main (int argc, char *argv[]) +{ + GstRTSPWFDServer *server; + guint id; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactoryWFD *factory; + GMainContext *context = NULL; + GSource * signal_handler_src = NULL; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + context = g_main_loop_get_context(loop); + + /* create a server instance */ + server = gst_rtsp_wfd_server_new (); + + gst_rtsp_server_set_address(GST_RTSP_SERVER(server), "192.168.3.100"); + //gst_rtsp_server_set_address(GST_RTSP_SERVER(server), "192.168.49.194"); + //gst_rtsp_server_set_address(GST_RTSP_SERVER(server), "192.168.49.20"); + gst_rtsp_server_set_service(GST_RTSP_SERVER(server), WFD_RTSP_PORT); + mounts = gst_rtsp_server_get_mount_points (GST_RTSP_SERVER(server)); + + factory = gst_rtsp_media_factory_wfd_new (); + + gst_rtsp_media_factory_set_launch (GST_RTSP_MEDIA_FACTORY(factory), + "( " VIDEO_PIPELINE " )"); + g_object_ref (factory); + gst_rtsp_mount_points_add_factory (mounts, TEST_MOUNT_POINT, GST_RTSP_MEDIA_FACTORY(factory)); + if (mounts) g_object_unref (mounts); + + /* attach the server to the default maincontext */ + if ((id = gst_rtsp_server_attach (GST_RTSP_SERVER_CAST(server), NULL)) == 0) + goto failed; + + signal_handler_src = (GSource *)g_unix_signal_source_new (SIGINT); + /* Set callback to be called when socket is readable */ + g_source_set_callback(signal_handler_src, teardown, server, NULL); + g_source_attach(signal_handler_src, context); + + /* start serving */ + g_main_loop_run (loop); + + /* cleanup */ + g_source_remove (id); + g_object_unref (server); + g_main_loop_unref (loop); + + return 0; + + /* ERRORS */ +failed: + { + g_print ("failed to attach the server\n"); + return -1; + } +} diff --git a/gst-rtsp-server.doap b/gst-rtsp-server.doap new file mode 100644 index 0000000..8dfa661 --- /dev/null +++ b/gst-rtsp-server.doap @@ -0,0 +1,160 @@ + + + GStreamer RTSP Server + gst-rtsp-server + + 1999-10-31 + +RTSP server library based on GStreamer + + +RTSP server library based on GStreamer + + + + + + C + + + + + + + + + + + + + 1.4.5 + 1.4 + + 2014-12-18 + + + + + + + 1.4.4 + 1.4 + + 2014-11-06 + + + + + + + 1.4.3 + 1.4 + + 2014-09-24 + + + + + + + 1.4.2 + 1.4 + + 2014-09-19 + + + + + + + 1.4.1 + 1.4 + + 2014-08-27 + + + + + + + 1.4.0 + 1.4 + + 2014-07-19 + + + + + + + 1.3.91 + 1.3 + + 2014-07-11 + + + + + + + 1.3.90 + 1.3 + + 2014-06-28 + + + + + + + 1.3.3 + 1.3 + + 2014-06-22 + + + + + + + 1.3.2 + 1.3 + + 2014-05-21 + + + + + + + 1.3.1 + 1.3 + + 2014-05-03 + + + + + + + 1.1.90 + 1.1 + + 2014-02-09 + + + + + + + Wim Taymans + 0d93fde052812d51a05fd86de9bdbf674423daa2 + + + + diff --git a/gst-rtsp-server.manifest b/gst-rtsp-server.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/gst-rtsp-server.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/gst/Makefile.am b/gst/Makefile.am new file mode 100644 index 0000000..e37bbc6 --- /dev/null +++ b/gst/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = rtsp-server diff --git a/gst/Makefile.in b/gst/Makefile.in new file mode 100644 index 0000000..35a2115 --- /dev/null +++ b/gst/Makefile.in @@ -0,0 +1,734 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = gst +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-docbook.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-default.m4 \ + $(top_srcdir)/common/m4/gst-doc.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAT_ENTRY_END = @CAT_ENTRY_END@ +CAT_ENTRY_START = @CAT_ENTRY_START@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@ +DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@ +DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@ +DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@ +DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ = @GLIB_REQ@ +GREP = @GREP@ +GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@ +GSTPD_PLUGINS_DIR = @GSTPD_PLUGINS_DIR@ +GSTPG_PLUGINS_DIR = @GSTPG_PLUGINS_DIR@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_BASE_CFLAGS = @GST_BASE_CFLAGS@ +GST_BASE_LIBS = @GST_BASE_LIBS@ +GST_CFLAGS = @GST_CFLAGS@ +GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@ +GST_CHECK_LIBS = @GST_CHECK_LIBS@ +GST_CURRENT = @GST_CURRENT@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBS = @GST_LIBS@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGINS_BAD_CFLAGS = @GST_PLUGINS_BAD_CFLAGS@ +GST_PLUGINS_BAD_DIR = @GST_PLUGINS_BAD_DIR@ +GST_PLUGINS_BAD_LIBS = @GST_PLUGINS_BAD_LIBS@ +GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@ +GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@ +GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@ +GST_PLUGINS_DIR = @GST_PLUGINS_DIR@ +GST_PLUGINS_GOOD_CFLAGS = @GST_PLUGINS_GOOD_CFLAGS@ +GST_PLUGINS_GOOD_DIR = @GST_PLUGINS_GOOD_DIR@ +GST_PLUGINS_GOOD_LIBS = @GST_PLUGINS_GOOD_LIBS@ +GST_REVISION = @GST_REVISION@ +GST_TOOLS_DIR = @GST_TOOLS_DIR@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ +HAVE_DVIPS = @HAVE_DVIPS@ +HAVE_EPSTOPDF = @HAVE_EPSTOPDF@ +HAVE_JADETEX = @HAVE_JADETEX@ +HAVE_PNGTOPNM = @HAVE_PNGTOPNM@ +HAVE_PNMTOPS = @HAVE_PNMTOPS@ +HAVE_PS2PDF = @HAVE_PS2PDF@ +HAVE_XMLLINT = @HAVE_XMLLINT@ +HAVE_XSLTPROC = @HAVE_XSLTPROC@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCGROUP_CFLAGS = @LIBCGROUP_CFLAGS@ +LIBCGROUP_LIBS = @LIBCGROUP_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +XML_CATALOG = @XML_CATALOG@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = rtsp-server +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu gst/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu gst/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gst/rtsp-server/Makefile.am b/gst/rtsp-server/Makefile.am new file mode 100644 index 0000000..60eaf3e --- /dev/null +++ b/gst/rtsp-server/Makefile.am @@ -0,0 +1,128 @@ +public_headers = \ + rtsp-auth.h \ + rtsp-address-pool.h \ + rtsp-context.h \ + rtsp-params.h \ + rtsp-sdp.h \ + rtsp-thread-pool.h \ + rtsp-media.h \ + rtsp-media-factory.h \ + rtsp-media-factory-wfd.h \ + rtsp-media-factory-uri.h \ + rtsp-mount-points.h \ + rtsp-permissions.h \ + rtsp-stream.h \ + rtsp-stream-transport.h \ + rtsp-session.h \ + rtsp-session-media.h \ + rtsp-session-pool.h \ + rtsp-token.h \ + rtsp-client-wfd.h \ + rtsp-client.h \ + rtsp-server-wfd.h \ + rtsp-server.h \ + gstwfdmessage.h + +c_sources = \ + rtsp-auth.c \ + rtsp-address-pool.c \ + rtsp-context.c \ + rtsp-params.c \ + rtsp-sdp.c \ + rtsp-thread-pool.c \ + rtsp-media.c \ + rtsp-media-factory.c \ + rtsp-media-factory-wfd.c \ + rtsp-media-factory-uri.c \ + rtsp-mount-points.c \ + rtsp-permissions.c \ + rtsp-stream.c \ + rtsp-stream-transport.c \ + rtsp-session.c \ + rtsp-session-media.c \ + rtsp-session-pool.c \ + rtsp-token.c \ + gstwfdmessage.c \ + rtsp-client-wfd.c \ + rtsp-client.c \ + rtsp-server-wfd.c \ + rtsp-server.c + +noinst_HEADERS = + +lib_LTLIBRARIES = \ + libgstrtspserver-@GST_API_VERSION@.la + +libgstrtspserver_@GST_API_VERSION@_la_SOURCES = \ + $(c_sources) + +libgstrtspserver_@GST_API_VERSION@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstrtspserver_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) +libgstrtspserver_@GST_API_VERSION@_la_LIBADD = \ + $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) \ + -lgstrtp-@GST_API_VERSION@ -lgstrtsp-@GST_API_VERSION@ \ + -lgstnet-@GST_API_VERSION@ \ + -lgstsdp-@GST_API_VERSION@ \ + -lgstapp-@GST_API_VERSION@ \ + $(GST_LIBS) $(GIO_LIBS) $(LIBM) + +libgstrtspserver_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/rtsp-server +libgstrtspserver_@GST_API_VERSION@include_HEADERS = $(public_headers) + +CLEANFILES = + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstRtspServer-@GST_API_VERSION@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstrtspserver_@GST_API_VERSION@include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstrtspserver_@GST_API_VERSION@_la_SOURCES)) + +GstRtspServer-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstrtspserver-@GST_API_VERSION@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_SCANNER) -v --namespace GstRtspServer \ + --nsversion=@GST_API_VERSION@ \ + --strip-prefix=Gst \ + --warn-all \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -DIN_GOBJECT_INTROSPECTION=1 \ + --c-include='gst/rtsp-server/rtsp-server.h' \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_API_VERSION@` \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-rtsp-@GST_API_VERSION@` \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-sdp-@GST_API_VERSION@` \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-net-@GST_API_VERSION@` \ + --library=libgstrtspserver-@GST_API_VERSION@.la \ + --include=Gst-@GST_API_VERSION@ \ + --include=GstRtsp-@GST_API_VERSION@ \ + --include=GstNet-@GST_API_VERSION@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_API_VERSION@ \ + --pkg gstreamer-rtsp-@GST_API_VERSION@ \ + --pkg gstreamer-net-@GST_API_VERSION@ \ + --pkg-export gstreamer-rtsp-server-@GST_API_VERSION@ \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_API_VERSION@` \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-rtsp-@GST_API_VERSION@` \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-sdp-@GST_API_VERSION@` \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-net-@GST_API_VERSION@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif diff --git a/gst/rtsp-server/Makefile.in b/gst/rtsp-server/Makefile.in new file mode 100644 index 0000000..c7c73ae --- /dev/null +++ b/gst/rtsp-server/Makefile.in @@ -0,0 +1,1065 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_INTROSPECTION_TRUE@am__append_1 = $(BUILT_GIRSOURCES) $(typelibs_DATA) +subdir = gst/rtsp-server +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp \ + $(libgstrtspserver_@GST_API_VERSION@include_HEADERS) \ + $(noinst_HEADERS) +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-docbook.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-default.m4 \ + $(top_srcdir)/common/m4/gst-doc.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ + "$(DESTDIR)$(typelibsdir)" \ + "$(DESTDIR)$(libgstrtspserver_@GST_API_VERSION@includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgstrtspserver_@GST_API_VERSION@_la_DEPENDENCIES = \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am__objects_1 = libgstrtspserver_@GST_API_VERSION@_la-rtsp-auth.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-address-pool.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-context.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-params.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-sdp.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-thread-pool.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-media.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory-uri.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-mount-points.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-permissions.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream-transport.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-session.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-media.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-pool.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-token.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-client.lo \ + libgstrtspserver_@GST_API_VERSION@_la-rtsp-server.lo +am_libgstrtspserver_@GST_API_VERSION@_la_OBJECTS = $(am__objects_1) +libgstrtspserver_@GST_API_VERSION@_la_OBJECTS = \ + $(am_libgstrtspserver_@GST_API_VERSION@_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgstrtspserver_@GST_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CCLD) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) \ + $(CFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgstrtspserver_@GST_API_VERSION@_la_SOURCES) +DIST_SOURCES = $(libgstrtspserver_@GST_API_VERSION@_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gir_DATA) $(typelibs_DATA) +HEADERS = $(libgstrtspserver_@GST_API_VERSION@include_HEADERS) \ + $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAT_ENTRY_END = @CAT_ENTRY_END@ +CAT_ENTRY_START = @CAT_ENTRY_START@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@ +DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@ +DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@ +DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@ +DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ = @GLIB_REQ@ +GREP = @GREP@ +GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@ +GSTPD_PLUGINS_DIR = @GSTPD_PLUGINS_DIR@ +GSTPG_PLUGINS_DIR = @GSTPG_PLUGINS_DIR@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_BASE_CFLAGS = @GST_BASE_CFLAGS@ +GST_BASE_LIBS = @GST_BASE_LIBS@ +GST_CFLAGS = @GST_CFLAGS@ +GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@ +GST_CHECK_LIBS = @GST_CHECK_LIBS@ +GST_CURRENT = @GST_CURRENT@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBS = @GST_LIBS@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGINS_BAD_CFLAGS = @GST_PLUGINS_BAD_CFLAGS@ +GST_PLUGINS_BAD_DIR = @GST_PLUGINS_BAD_DIR@ +GST_PLUGINS_BAD_LIBS = @GST_PLUGINS_BAD_LIBS@ +GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@ +GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@ +GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@ +GST_PLUGINS_DIR = @GST_PLUGINS_DIR@ +GST_PLUGINS_GOOD_CFLAGS = @GST_PLUGINS_GOOD_CFLAGS@ +GST_PLUGINS_GOOD_DIR = @GST_PLUGINS_GOOD_DIR@ +GST_PLUGINS_GOOD_LIBS = @GST_PLUGINS_GOOD_LIBS@ +GST_REVISION = @GST_REVISION@ +GST_TOOLS_DIR = @GST_TOOLS_DIR@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ +HAVE_DVIPS = @HAVE_DVIPS@ +HAVE_EPSTOPDF = @HAVE_EPSTOPDF@ +HAVE_JADETEX = @HAVE_JADETEX@ +HAVE_PNGTOPNM = @HAVE_PNGTOPNM@ +HAVE_PNMTOPS = @HAVE_PNMTOPS@ +HAVE_PS2PDF = @HAVE_PS2PDF@ +HAVE_XMLLINT = @HAVE_XMLLINT@ +HAVE_XSLTPROC = @HAVE_XSLTPROC@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCGROUP_CFLAGS = @LIBCGROUP_CFLAGS@ +LIBCGROUP_LIBS = @LIBCGROUP_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +XML_CATALOG = @XML_CATALOG@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +public_headers = \ + rtsp-auth.h \ + rtsp-address-pool.h \ + rtsp-context.h \ + rtsp-params.h \ + rtsp-sdp.h \ + rtsp-thread-pool.h \ + rtsp-media.h \ + rtsp-media-factory.h \ + rtsp-media-factory-uri.h \ + rtsp-mount-points.h \ + rtsp-permissions.h \ + rtsp-stream.h \ + rtsp-stream-transport.h \ + rtsp-session.h \ + rtsp-session-media.h \ + rtsp-session-pool.h \ + rtsp-token.h \ + rtsp-client.h \ + rtsp-server.h + +c_sources = \ + rtsp-auth.c \ + rtsp-address-pool.c \ + rtsp-context.c \ + rtsp-params.c \ + rtsp-sdp.c \ + rtsp-thread-pool.c \ + rtsp-media.c \ + rtsp-media-factory.c \ + rtsp-media-factory-uri.c \ + rtsp-mount-points.c \ + rtsp-permissions.c \ + rtsp-stream.c \ + rtsp-stream-transport.c \ + rtsp-session.c \ + rtsp-session-media.c \ + rtsp-session-pool.c \ + rtsp-token.c \ + rtsp-client.c \ + rtsp-server.c + +noinst_HEADERS = +lib_LTLIBRARIES = \ + libgstrtspserver-@GST_API_VERSION@.la + +libgstrtspserver_@GST_API_VERSION@_la_SOURCES = \ + $(c_sources) + +libgstrtspserver_@GST_API_VERSION@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstrtspserver_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) +libgstrtspserver_@GST_API_VERSION@_la_LIBADD = \ + $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) \ + -lgstrtp-@GST_API_VERSION@ -lgstrtsp-@GST_API_VERSION@ \ + -lgstnet-@GST_API_VERSION@ \ + -lgstsdp-@GST_API_VERSION@ \ + -lgstapp-@GST_API_VERSION@ \ + $(GST_LIBS) $(GIO_LIBS) $(LIBM) + +libgstrtspserver_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/rtsp-server +libgstrtspserver_@GST_API_VERSION@include_HEADERS = $(public_headers) +CLEANFILES = $(am__append_1) +@HAVE_INTROSPECTION_TRUE@BUILT_GIRSOURCES = GstRtspServer-@GST_API_VERSION@.gir +@HAVE_INTROSPECTION_TRUE@gir_headers = $(patsubst %,$(srcdir)/%, $(libgstrtspserver_@GST_API_VERSION@include_HEADERS)) +@HAVE_INTROSPECTION_TRUE@gir_sources = $(patsubst %,$(srcdir)/%, $(libgstrtspserver_@GST_API_VERSION@_la_SOURCES)) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +@HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 +@HAVE_INTROSPECTION_TRUE@gir_DATA = $(BUILT_GIRSOURCES) +@HAVE_INTROSPECTION_TRUE@typelibsdir = $(libdir)/girepository-1.0/ +@HAVE_INTROSPECTION_TRUE@typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu gst/rtsp-server/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu gst/rtsp-server/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgstrtspserver-@GST_API_VERSION@.la: $(libgstrtspserver_@GST_API_VERSION@_la_OBJECTS) $(libgstrtspserver_@GST_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libgstrtspserver_@GST_API_VERSION@_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgstrtspserver_@GST_API_VERSION@_la_LINK) -rpath $(libdir) $(libgstrtspserver_@GST_API_VERSION@_la_OBJECTS) $(libgstrtspserver_@GST_API_VERSION@_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-address-pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-auth.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-client.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-context.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory-uri.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-mount-points.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-params.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-permissions.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-sdp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-server.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-media.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream-transport.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-thread-pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-token.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-auth.lo: rtsp-auth.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-auth.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-auth.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-auth.lo `test -f 'rtsp-auth.c' || echo '$(srcdir)/'`rtsp-auth.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-auth.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-auth.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-auth.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-auth.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-auth.lo `test -f 'rtsp-auth.c' || echo '$(srcdir)/'`rtsp-auth.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-address-pool.lo: rtsp-address-pool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-address-pool.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-address-pool.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-address-pool.lo `test -f 'rtsp-address-pool.c' || echo '$(srcdir)/'`rtsp-address-pool.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-address-pool.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-address-pool.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-address-pool.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-address-pool.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-address-pool.lo `test -f 'rtsp-address-pool.c' || echo '$(srcdir)/'`rtsp-address-pool.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-context.lo: rtsp-context.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-context.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-context.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-context.lo `test -f 'rtsp-context.c' || echo '$(srcdir)/'`rtsp-context.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-context.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-context.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-context.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-context.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-context.lo `test -f 'rtsp-context.c' || echo '$(srcdir)/'`rtsp-context.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-params.lo: rtsp-params.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-params.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-params.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-params.lo `test -f 'rtsp-params.c' || echo '$(srcdir)/'`rtsp-params.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-params.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-params.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-params.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-params.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-params.lo `test -f 'rtsp-params.c' || echo '$(srcdir)/'`rtsp-params.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-sdp.lo: rtsp-sdp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-sdp.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-sdp.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-sdp.lo `test -f 'rtsp-sdp.c' || echo '$(srcdir)/'`rtsp-sdp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-sdp.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-sdp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-sdp.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-sdp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-sdp.lo `test -f 'rtsp-sdp.c' || echo '$(srcdir)/'`rtsp-sdp.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-thread-pool.lo: rtsp-thread-pool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-thread-pool.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-thread-pool.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-thread-pool.lo `test -f 'rtsp-thread-pool.c' || echo '$(srcdir)/'`rtsp-thread-pool.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-thread-pool.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-thread-pool.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-thread-pool.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-thread-pool.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-thread-pool.lo `test -f 'rtsp-thread-pool.c' || echo '$(srcdir)/'`rtsp-thread-pool.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-media.lo: rtsp-media.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-media.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-media.lo `test -f 'rtsp-media.c' || echo '$(srcdir)/'`rtsp-media.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-media.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-media.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-media.lo `test -f 'rtsp-media.c' || echo '$(srcdir)/'`rtsp-media.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory.lo: rtsp-media-factory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory.lo `test -f 'rtsp-media-factory.c' || echo '$(srcdir)/'`rtsp-media-factory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-media-factory.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory.lo `test -f 'rtsp-media-factory.c' || echo '$(srcdir)/'`rtsp-media-factory.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory-uri.lo: rtsp-media-factory-uri.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory-uri.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory-uri.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory-uri.lo `test -f 'rtsp-media-factory-uri.c' || echo '$(srcdir)/'`rtsp-media-factory-uri.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory-uri.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory-uri.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-media-factory-uri.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory-uri.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-media-factory-uri.lo `test -f 'rtsp-media-factory-uri.c' || echo '$(srcdir)/'`rtsp-media-factory-uri.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-mount-points.lo: rtsp-mount-points.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-mount-points.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-mount-points.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-mount-points.lo `test -f 'rtsp-mount-points.c' || echo '$(srcdir)/'`rtsp-mount-points.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-mount-points.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-mount-points.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-mount-points.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-mount-points.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-mount-points.lo `test -f 'rtsp-mount-points.c' || echo '$(srcdir)/'`rtsp-mount-points.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-permissions.lo: rtsp-permissions.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-permissions.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-permissions.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-permissions.lo `test -f 'rtsp-permissions.c' || echo '$(srcdir)/'`rtsp-permissions.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-permissions.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-permissions.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-permissions.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-permissions.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-permissions.lo `test -f 'rtsp-permissions.c' || echo '$(srcdir)/'`rtsp-permissions.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream.lo: rtsp-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream.lo `test -f 'rtsp-stream.c' || echo '$(srcdir)/'`rtsp-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-stream.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream.lo `test -f 'rtsp-stream.c' || echo '$(srcdir)/'`rtsp-stream.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream-transport.lo: rtsp-stream-transport.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream-transport.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream-transport.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream-transport.lo `test -f 'rtsp-stream-transport.c' || echo '$(srcdir)/'`rtsp-stream-transport.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream-transport.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream-transport.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-stream-transport.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream-transport.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-stream-transport.lo `test -f 'rtsp-stream-transport.c' || echo '$(srcdir)/'`rtsp-stream-transport.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-session.lo: rtsp-session.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-session.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-session.lo `test -f 'rtsp-session.c' || echo '$(srcdir)/'`rtsp-session.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-session.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-session.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-session.lo `test -f 'rtsp-session.c' || echo '$(srcdir)/'`rtsp-session.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-media.lo: rtsp-session-media.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-media.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-media.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-media.lo `test -f 'rtsp-session-media.c' || echo '$(srcdir)/'`rtsp-session-media.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-media.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-media.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-session-media.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-media.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-media.lo `test -f 'rtsp-session-media.c' || echo '$(srcdir)/'`rtsp-session-media.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-pool.lo: rtsp-session-pool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-pool.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-pool.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-pool.lo `test -f 'rtsp-session-pool.c' || echo '$(srcdir)/'`rtsp-session-pool.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-pool.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-pool.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-session-pool.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-pool.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-session-pool.lo `test -f 'rtsp-session-pool.c' || echo '$(srcdir)/'`rtsp-session-pool.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-token.lo: rtsp-token.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-token.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-token.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-token.lo `test -f 'rtsp-token.c' || echo '$(srcdir)/'`rtsp-token.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-token.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-token.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-token.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-token.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-token.lo `test -f 'rtsp-token.c' || echo '$(srcdir)/'`rtsp-token.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-client.lo: rtsp-client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-client.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-client.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-client.lo `test -f 'rtsp-client.c' || echo '$(srcdir)/'`rtsp-client.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-client.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-client.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-client.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-client.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-client.lo `test -f 'rtsp-client.c' || echo '$(srcdir)/'`rtsp-client.c + +libgstrtspserver_@GST_API_VERSION@_la-rtsp-server.lo: rtsp-server.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstrtspserver_@GST_API_VERSION@_la-rtsp-server.lo -MD -MP -MF $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-server.Tpo -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-server.lo `test -f 'rtsp-server.c' || echo '$(srcdir)/'`rtsp-server.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-server.Tpo $(DEPDIR)/libgstrtspserver_@GST_API_VERSION@_la-rtsp-server.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp-server.c' object='libgstrtspserver_@GST_API_VERSION@_la-rtsp-server.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstrtspserver_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstrtspserver_@GST_API_VERSION@_la-rtsp-server.lo `test -f 'rtsp-server.c' || echo '$(srcdir)/'`rtsp-server.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-typelibsDATA: $(typelibs_DATA) + @$(NORMAL_INSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibsdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibsdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibsdir)" || exit $$?; \ + done + +uninstall-typelibsDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibsdir)'; $(am__uninstall_files_from_dir) +install-libgstrtspserver_@GST_API_VERSION@includeHEADERS: $(libgstrtspserver_@GST_API_VERSION@include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libgstrtspserver_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstrtspserver_@GST_API_VERSION@includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libgstrtspserver_@GST_API_VERSION@includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libgstrtspserver_@GST_API_VERSION@includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgstrtspserver_@GST_API_VERSION@includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgstrtspserver_@GST_API_VERSION@includedir)" || exit $$?; \ + done + +uninstall-libgstrtspserver_@GST_API_VERSION@includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libgstrtspserver_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstrtspserver_@GST_API_VERSION@includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libgstrtspserver_@GST_API_VERSION@includedir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibsdir)" "$(DESTDIR)$(libgstrtspserver_@GST_API_VERSION@includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-girDATA \ + install-libgstrtspserver_@GST_API_VERSION@includeHEADERS \ + install-typelibsDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-girDATA uninstall-libLTLIBRARIES \ + uninstall-libgstrtspserver_@GST_API_VERSION@includeHEADERS \ + uninstall-typelibsDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist-am ctags-am \ + distclean distclean-compile distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-girDATA \ + install-html install-html-am install-info install-info-am \ + install-libLTLIBRARIES \ + install-libgstrtspserver_@GST_API_VERSION@includeHEADERS \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip install-typelibsDATA installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am uninstall-girDATA \ + uninstall-libLTLIBRARIES \ + uninstall-libgstrtspserver_@GST_API_VERSION@includeHEADERS \ + uninstall-typelibsDATA + + +@HAVE_INTROSPECTION_TRUE@GstRtspServer-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstrtspserver-@GST_API_VERSION@.la +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ +@HAVE_INTROSPECTION_TRUE@ $(INTROSPECTION_SCANNER) -v --namespace GstRtspServer \ +@HAVE_INTROSPECTION_TRUE@ --nsversion=@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --strip-prefix=Gst \ +@HAVE_INTROSPECTION_TRUE@ --warn-all \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_srcdir) \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir) \ +@HAVE_INTROSPECTION_TRUE@ -DIN_GOBJECT_INTROSPECTION=1 \ +@HAVE_INTROSPECTION_TRUE@ --c-include='gst/rtsp-server/rtsp-server.h' \ +@HAVE_INTROSPECTION_TRUE@ --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_API_VERSION@` \ +@HAVE_INTROSPECTION_TRUE@ --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-rtsp-@GST_API_VERSION@` \ +@HAVE_INTROSPECTION_TRUE@ --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-sdp-@GST_API_VERSION@` \ +@HAVE_INTROSPECTION_TRUE@ --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-net-@GST_API_VERSION@` \ +@HAVE_INTROSPECTION_TRUE@ --library=libgstrtspserver-@GST_API_VERSION@.la \ +@HAVE_INTROSPECTION_TRUE@ --include=Gst-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --include=GstRtsp-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --include=GstNet-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --libtool="$(top_builddir)/libtool" \ +@HAVE_INTROSPECTION_TRUE@ --pkg gstreamer-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --pkg gstreamer-rtsp-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --pkg gstreamer-net-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --pkg-export gstreamer-rtsp-server-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --output $@ \ +@HAVE_INTROSPECTION_TRUE@ $(gir_headers) \ +@HAVE_INTROSPECTION_TRUE@ $(gir_sources) + +@HAVE_INTROSPECTION_TRUE@%.typelib: %.gir $(INTROSPECTION_COMPILER) +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ +@HAVE_INTROSPECTION_TRUE@ $(INTROSPECTION_COMPILER) \ +@HAVE_INTROSPECTION_TRUE@ --includedir=$(srcdir) \ +@HAVE_INTROSPECTION_TRUE@ --includedir=$(builddir) \ +@HAVE_INTROSPECTION_TRUE@ --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_API_VERSION@` \ +@HAVE_INTROSPECTION_TRUE@ --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-rtsp-@GST_API_VERSION@` \ +@HAVE_INTROSPECTION_TRUE@ --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-sdp-@GST_API_VERSION@` \ +@HAVE_INTROSPECTION_TRUE@ --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-net-@GST_API_VERSION@` \ +@HAVE_INTROSPECTION_TRUE@ $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gst/rtsp-server/gstwfdmessage.c b/gst/rtsp-server/gstwfdmessage.c new file mode 100755 index 0000000..46301bd --- /dev/null +++ b/gst/rtsp-server/gstwfdmessage.c @@ -0,0 +1,1963 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * 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. + */ +/* + * Unless otherwise indicated, Source Code is licensed under MIT license. + * See further explanation attached in License Statement (distributed in the file + * LICENSE). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * SECTION:gstwfdmessage + * @short_description: Helper methods for dealing with WFD messages + * + * + * + * The GstWFDMessage helper functions makes it easy to parse and create WFD + * messages. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include + +#include "gstwfdmessage.h" + +#define EDID_BLOCK_SIZE 128 + +#define FREE_STRING(field) g_free (field); (field) = NULL +#define REPLACE_STRING(field, val) FREE_STRING(field); (field) = g_strdup (val) + +#define INIT_ARRAY(field, type, init_func) \ +G_STMT_START { \ + if (field) { \ + guint i; \ + for(i = 0; i < (field)->len; i++) \ + init_func (&g_array_index ((field), type, i)); \ + g_array_set_size ((field), 0); \ + } \ + else \ + (field) = g_array_new (FALSE, TRUE, sizeof (type)); \ +} G_STMT_END + +#define FREE_ARRAY(field) \ +G_STMT_START { \ + if (field) \ + g_array_free ((field), TRUE); \ + (field) = NULL; \ +} G_STMT_END + +#define DEFINE_STRING_SETTER(field) \ +GstWFDResult gst_wfd_message_set_##field (GstWFDMessage *msg, const gchar *val) { \ + g_free (msg->field); \ + msg->field = g_strdup (val); \ + return GST_WFD_OK; \ +} +#define DEFINE_STRING_GETTER(field) \ +const gchar* gst_wfd_message_get_##field (const GstWFDMessage *msg) { \ + return msg->field; \ +} + +#define DEFINE_ARRAY_LEN(field) \ +guint gst_wfd_message_##field##_len (const GstWFDMessage *msg) { \ + return msg->field->len; \ +} +#define DEFINE_ARRAY_GETTER(method, field, type) \ +const type * gst_wfd_message_get_##method (const GstWFDMessage *msg, guint idx) { \ + return &g_array_index (msg->field, type, idx); \ +} +#define DEFINE_PTR_ARRAY_GETTER(method, field, type) \ +const type gst_wfd_message_get_##method (const GstWFDMessage *msg, guint idx) { \ + return g_array_index (msg->field, type, idx); \ +} +#define DEFINE_ARRAY_INSERT(method, field, intype, dup_method, type) \ +GstWFDResult gst_wfd_message_insert_##method (GstWFDMessage *msg, gint idx, intype val) { \ + type vt; \ + type* v = &vt; \ + dup_method (v, val); \ + if (idx == -1) \ + g_array_append_val (msg->field, vt); \ + else \ + g_array_insert_val (msg->field, idx, vt); \ + return GST_WFD_OK; \ +} + +#define DEFINE_ARRAY_REPLACE(method, field, intype, free_method, dup_method, type) \ +GstWFDResult gst_wfd_message_replace_##method (GstWFDMessage *msg, guint idx, intype val) { \ + type *v = &g_array_index (msg->field, type, idx); \ + free_method (v); \ + dup_method (v, val); \ + return GST_WFD_OK; \ +} +#define DEFINE_ARRAY_REMOVE(method, field, type, free_method) \ +GstWFDResult gst_wfd_message_remove_##method (GstWFDMessage *msg, guint idx) { \ + type *v = &g_array_index (msg->field, type, idx); \ + free_method (v); \ + g_array_remove_index (msg->field, idx); \ + return GST_WFD_OK; \ +} +#define DEFINE_ARRAY_ADDER(method, type) \ +GstWFDResult gst_wfd_message_add_##method (GstWFDMessage *msg, const type val) { \ + return gst_wfd_message_insert_##method (msg, -1, val); \ +} + +#define dup_string(v,val) ((*v) = g_strdup (val)) +#define INIT_STR_ARRAY(field) \ + INIT_ARRAY (field, gchar *, free_string) +#define DEFINE_STR_ARRAY_GETTER(method, field) \ + DEFINE_PTR_ARRAY_GETTER(method, field, gchar *) +#define DEFINE_STR_ARRAY_INSERT(method, field) \ + DEFINE_ARRAY_INSERT (method, field, const gchar *, dup_string, gchar *) +#define DEFINE_STR_ARRAY_ADDER(method, field) \ + DEFINE_ARRAY_ADDER (method, gchar *) +#define DEFINE_STR_ARRAY_REPLACE(method, field) \ + DEFINE_ARRAY_REPLACE (method, field, const gchar *, free_string, dup_string, gchar *) +#define DEFINE_STR_ARRAY_REMOVE(method, field) \ + DEFINE_ARRAY_REMOVE (method, field, gchar *, free_string) + +static GstWFDMessage *gst_wfd_message_boxed_copy (GstWFDMessage * orig); +static void gst_wfd_message_boxed_free (GstWFDMessage * msg); + +G_DEFINE_BOXED_TYPE (GstWFDMessage, gst_wfd_message, gst_wfd_message_boxed_copy, + gst_wfd_message_boxed_free); + +static GstWFDMessage * +gst_wfd_message_boxed_copy (GstWFDMessage * orig) +{ + GstWFDMessage *copy; + + if (gst_wfd_message_copy (orig, ©) == GST_WFD_OK) + return copy; + + return NULL; +} + +static void +gst_wfd_message_boxed_free (GstWFDMessage * msg) +{ + gst_wfd_message_free (msg); +} + +/** + * gst_wfd_message_new: + * @msg: (out) (transfer full): pointer to new #GstWFDMessage + * + * Allocate a new GstWFDMessage and store the result in @msg. + * + * Returns: a #GstWFDResult. + */ +GstWFDResult +gst_wfd_message_new (GstWFDMessage ** msg) +{ + GstWFDMessage *newmsg; + + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + newmsg = g_new0 (GstWFDMessage, 1); + + *msg = newmsg; + + return gst_wfd_message_init (newmsg); +} + +/** + * gst_wfd_message_init: + * @msg: a #GstWFDMessage + * + * Initialize @msg so that its contents are as if it was freshly allocated + * with gst_wfd_message_new(). This function is mostly used to initialize a message + * allocated on the stack. gst_wfd_message_uninit() undoes this operation. + * + * When this function is invoked on newly allocated data (with malloc or on the + * stack), its contents should be set to 0 before calling this function. + * + * Returns: a #GstWFDResult. + */ +GstWFDResult +gst_wfd_message_init (GstWFDMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + return GST_WFD_OK; +} + +/** + * gst_wfd_message_uninit: + * @msg: a #GstWFDMessage + * + * Free all resources allocated in @msg. @msg should not be used anymore after + * this function. This function should be used when @msg was allocated on the + * stack and initialized with gst_wfd_message_init(). + * + * Returns: a #GstWFDResult. + */ +GstWFDResult +gst_wfd_message_uninit (GstWFDMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (msg->audio_codecs) { + guint i = 0; + if (msg->audio_codecs->list) { + for (; i < msg->audio_codecs->count; i++) { + FREE_STRING(msg->audio_codecs->list[i].audio_format); + msg->audio_codecs->list[i].modes = 0; + msg->audio_codecs->list[i].latency = 0; + } + FREE_STRING(msg->audio_codecs->list); + } + FREE_STRING(msg->audio_codecs); + } + + if (msg->video_formats) { + FREE_STRING(msg->video_formats->list); + FREE_STRING(msg->video_formats); + } + + if (msg->video_3d_formats) { + FREE_STRING(msg->video_3d_formats->list); + FREE_STRING(msg->video_3d_formats); + } + + if (msg->content_protection) { + if (msg->content_protection->hdcp2_spec) { + FREE_STRING(msg->content_protection->hdcp2_spec->hdcpversion); + FREE_STRING(msg->content_protection->hdcp2_spec->TCPPort); + FREE_STRING(msg->content_protection->hdcp2_spec); + } + FREE_STRING(msg->content_protection); + } + + if (msg->display_edid) { + if (msg->display_edid->edid_payload) + FREE_STRING(msg->display_edid->edid_payload); + FREE_STRING(msg->display_edid); + } + + if (msg->coupled_sink) { + if (msg->coupled_sink->coupled_sink_cap) { + FREE_STRING(msg->coupled_sink->coupled_sink_cap->sink_address); + FREE_STRING(msg->coupled_sink->coupled_sink_cap); + } + FREE_STRING(msg->coupled_sink); + } + + if (msg->trigger_method) { + FREE_STRING(msg->trigger_method->wfd_trigger_method); + FREE_STRING(msg->trigger_method); + } + + if (msg->presentation_url) { + FREE_STRING(msg->presentation_url->wfd_url0); + FREE_STRING(msg->presentation_url->wfd_url1); + FREE_STRING(msg->presentation_url); + } + + if (msg->client_rtp_ports) { + FREE_STRING(msg->client_rtp_ports->profile); + FREE_STRING(msg->client_rtp_ports->mode); + FREE_STRING(msg->client_rtp_ports); + } + + if (msg->route) { + FREE_STRING(msg->route->destination); + FREE_STRING(msg->route); + } + + if (msg->I2C) { + FREE_STRING(msg->I2C); + } + + if (msg->av_format_change_timing) { + FREE_STRING(msg->av_format_change_timing); + } + + if (msg->preferred_display_mode) { + FREE_STRING(msg->preferred_display_mode); + } + + if (msg->standby_resume_capability) { + FREE_STRING(msg->standby_resume_capability); + } + + if (msg->standby) { + FREE_STRING(msg->standby); + } + + if (msg->connector_type) { + FREE_STRING(msg->connector_type); + } + + if (msg->idr_request) { + FREE_STRING(msg->idr_request); + } + + return GST_WFD_OK; +} + +/** + * gst_wfd_message_copy: + * @msg: a #GstWFDMessage + * @copy: (out) (transfer full): pointer to new #GstWFDMessage + * + * Allocate a new copy of @msg and store the result in @copy. The value in + * @copy should be release with gst_wfd_message_free function. + * + * Returns: a #GstWFDResult + * + * Since: 1.6 + */ +GstWFDResult +gst_wfd_message_copy (const GstWFDMessage * msg, GstWFDMessage ** copy) +{ + GstWFDResult ret; + GstWFDMessage *cp; + + if (msg == NULL) + return GST_WFD_EINVAL; + + ret = gst_wfd_message_new (copy); + if (ret != GST_WFD_OK) + return ret; + + cp = *copy; + + /* TODO-WFD */ + if (msg->client_rtp_ports) { + cp->client_rtp_ports = g_malloc (sizeof (GstWFDClientRtpPorts)); + if (cp->client_rtp_ports) { + cp->client_rtp_ports->profile = g_strdup (msg->client_rtp_ports->profile); + cp->client_rtp_ports->rtp_port0 = msg->client_rtp_ports->rtp_port0; + cp->client_rtp_ports->rtp_port1 = msg->client_rtp_ports->rtp_port1; + cp->client_rtp_ports->mode = g_strdup (msg->client_rtp_ports->mode); + } + } + + return GST_WFD_OK; +} + + +static void +_read_string_space_ended (gchar * dest, guint size, gchar * src) +{ + guint idx = 0; + + while (!g_ascii_isspace (*src) && *src != '\0') { + if (idx < size - 1) + dest[idx++] = *src; + src++; + } + + if (size > 0) + dest[idx] = '\0'; + + return; +} + +static void +_read_string_attr_and_value (gchar * attr, gchar * value, guint tsize, + guint vsize, gchar del, gchar * src) +{ + guint idx; + + idx = 0; + + while (*src != del && *src != '\0') { + if (idx < tsize - 1) + attr[idx++] = *src; + src++; + } + + if (tsize > 0) + attr[idx] = '\0'; + + src++; + idx = 0; + + while (*src != '\0') { + if (idx < vsize - 1) + value[idx++] = *src; + src++; + } + + if (vsize > 0) + value[idx] = '\0'; + + return; +} + +static void +gst_wfd_parse_attribute (gchar * buffer, GstWFDMessage * msg) +{ + gchar attr[8192] = { 0 }; + gchar value[8192] = { 0 }; + gchar temp[8192] = { 0 }; + gchar *p = buffer; + gchar *v = value; + +#define WFD_SKIP_SPACE(q) if (*q && g_ascii_isspace (*q)) q++ +#define WFD_SKIP_EQUAL(q) if (*q && *q == '=') q++ +#define WFD_SKIP_COMMA(q) if (*q && g_ascii_ispunct (*q)) q++ +#define WFD_READ_STRING(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); REPLACE_STRING (field, temp) +#define WFD_READ_UINT32(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 16) +#define WFD_READ_UINT32_DIGIT(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 10) + + _read_string_attr_and_value (attr, value, sizeof (attr), sizeof (value), ':', + p); + + if (!g_strcmp0 (attr, GST_STRING_WFD_AUDIO_CODECS)) { + msg->audio_codecs = g_new0 (GstWFDAudioCodeclist, 1); + if (strlen (v)) { + guint i = 0; + msg->audio_codecs->count = strlen (v) / 16; + msg->audio_codecs->list = + g_new0 (GstWFDAudioCodec, msg->audio_codecs->count); + for (; i < msg->audio_codecs->count; i++) { + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->audio_codecs->list[i].audio_format); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->audio_codecs->list[i].modes); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->audio_codecs->list[i].latency); + WFD_SKIP_COMMA (v); + } + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_VIDEO_FORMATS)) { + msg->video_formats = g_new0 (GstWFDVideoCodeclist, 1); + if (strlen (v)) { + msg->video_formats->count = 1; + msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->native); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats-> + list->preferred_display_mode_supported); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.profile); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.level); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec. + misc_params.CEA_Support); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec. + misc_params.VESA_Support); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec. + misc_params.HH_Support); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec. + misc_params.latency); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec. + misc_params.min_slice_size); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec. + misc_params.slice_enc_params); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec. + misc_params.frame_rate_control_support); + WFD_SKIP_SPACE (v); + if (msg->video_formats->list->preferred_display_mode_supported == 1) { + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_hres); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_vres); + WFD_SKIP_SPACE (v); + } + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_3D_VIDEO_FORMATS)) { + msg->video_3d_formats = g_new0 (GstWFD3DFormats, 1); + if (strlen (v)) { + msg->video_3d_formats->count = 1; + msg->video_3d_formats->list = g_new0 (GstWFD3dCapList, 1); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_3d_formats->list->native); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_3d_formats-> + list->preferred_display_mode_supported); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.profile); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.level); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec. + misc_params.video_3d_capability); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec. + misc_params.latency); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec. + misc_params.min_slice_size); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec. + misc_params.slice_enc_params); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec. + misc_params.frame_rate_control_support); + WFD_SKIP_SPACE (v); + if (msg->video_formats->list->preferred_display_mode_supported == 1) { + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_hres); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_vres); + WFD_SKIP_SPACE (v); + } + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_CONTENT_PROTECTION)) { + msg->content_protection = g_new0 (GstWFDContentProtection, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + msg->content_protection->hdcp2_spec = g_new0 (GstWFDHdcp2Spec, 1); + if (strstr (v, "none")) { + msg->content_protection->hdcp2_spec->hdcpversion = g_strdup ("none"); + } else { + WFD_READ_STRING (msg->content_protection->hdcp2_spec->hdcpversion); + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->content_protection->hdcp2_spec->TCPPort); + } + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_DISPLAY_EDID)) { + msg->display_edid = g_new0 (GstWFDDisplayEdid, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + if (strstr (v, "none")) { + msg->display_edid->edid_supported = 0; + } else { + msg->display_edid->edid_supported = 1; + WFD_READ_UINT32 (msg->display_edid->edid_block_count); + WFD_SKIP_SPACE (v); + if (msg->display_edid->edid_block_count) { + gchar *edid_string = v; + int i = 0, j = 0; + guint32 payload_size = + EDID_BLOCK_SIZE * msg->display_edid->edid_block_count; + msg->display_edid->edid_payload = g_malloc (payload_size); + for (; + i < (EDID_BLOCK_SIZE * msg->display_edid->edid_block_count * 2); + j++) { + int k = 0, kk = 0; + if (edid_string[i] > 0x29 && edid_string[i] < 0x40) + k = edid_string[i] - 48; + else if (edid_string[i] > 0x60 && edid_string[i] < 0x67) + k = edid_string[i] - 87; + else if (edid_string[i] > 0x40 && edid_string[i] < 0x47) + k = edid_string[i] - 55; + + if (edid_string[i + 1] > 0x29 && edid_string[i + 1] < 0x40) + kk = edid_string[i + 1] - 48; + else if (edid_string[i + 1] > 0x60 && edid_string[i + 1] < 0x67) + kk = edid_string[i + 1] - 87; + else if (edid_string[i + 1] > 0x40 && edid_string[i + 1] < 0x47) + kk = edid_string[i + 1] - 55; + + msg->display_edid->edid_payload[j] = (k << 4) | kk; + i += 2; + } + //memcpy(msg->display_edid->edid_payload, v, payload_size); + v += (payload_size * 2); + } else + v += strlen (v); + } + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_COUPLED_SINK)) { + msg->coupled_sink = g_new0 (GstWFDCoupledSink, 1); + if (strlen (v)) { + msg->coupled_sink->coupled_sink_cap = g_new0 (GstWFDCoupled_sink_cap, 1); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->coupled_sink->coupled_sink_cap->status); + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->coupled_sink->coupled_sink_cap->sink_address); + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_TRIGGER_METHOD)) { + msg->trigger_method = g_new0 (GstWFDTriggerMethod, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->trigger_method->wfd_trigger_method); + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_PRESENTATION_URL)) { + msg->presentation_url = g_new0 (GstWFDPresentationUrl, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->presentation_url->wfd_url0); + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->presentation_url->wfd_url1); + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_CLIENT_RTP_PORTS)) { + msg->client_rtp_ports = g_new0 (GstWFDClientRtpPorts, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->client_rtp_ports->profile); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->client_rtp_ports->rtp_port0); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->client_rtp_ports->rtp_port1); + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->client_rtp_ports->mode); + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_ROUTE)) { + msg->route = g_new0 (GstWFDRoute, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->route->destination); + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_I2C)) { + msg->I2C = g_new0 (GstWFDI2C, 1); + if (strlen (v)) { + msg->I2C->I2CPresent = TRUE; + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->I2C->I2C_port); + if (msg->I2C->I2C_port) + msg->I2C->I2CPresent = TRUE; + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING)) { + msg->av_format_change_timing = g_new0 (GstWFDAVFormatChangeTiming, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->av_format_change_timing->PTS); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->av_format_change_timing->DTS); + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_PREFERRED_DISPLAY_MODE)) { + msg->preferred_display_mode = g_new0 (GstWFDPreferredDisplayMode, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + if (!strstr (v, "none")) { + msg->preferred_display_mode->displaymodesupported = FALSE; + } else { + WFD_READ_UINT32 (msg->preferred_display_mode->p_clock); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->HB); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->HSPOL_HSOFF); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->HSW); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->V); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->VB); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->VSPOL_VSOFF); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->VSW); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->VBS3D); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->V2d_s3d_modes); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->P_depth); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.profile); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.level); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. + misc_params.CEA_Support); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. + misc_params.VESA_Support); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. + misc_params.HH_Support); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. + misc_params.latency); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. + misc_params.min_slice_size); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. + misc_params.slice_enc_params); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. + misc_params.frame_rate_control_support); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.max_hres); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.max_vres); + WFD_SKIP_SPACE (v); + } + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_STANDBY_RESUME_CAPABILITY)) { + msg->standby_resume_capability = g_new0 (GstWFDStandbyResumeCapability, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + if (!g_strcmp0 (v, "supported")) + msg->standby_resume_capability->standby_resume_cap = TRUE; + else + msg->standby_resume_capability->standby_resume_cap = FALSE; + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_STANDBY)) { + msg->standby = g_new0 (GstWFDStandby, 1); + msg->standby->wfd_standby = TRUE; + } else if (!g_strcmp0 (attr, GST_STRING_WFD_CONNECTOR_TYPE)) { + msg->connector_type = g_new0 (GstWFDConnectorType, 1); + if (strlen (v)) { + msg->connector_type->supported = TRUE; + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->connector_type->connector_type); + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD_IDR_REQUEST)) { + msg->idr_request = g_new0 (GstWFDIdrRequest, 1); + msg->idr_request->idr_request = TRUE; + } + return; +} + +/** + * gst_wfd_message_parse_buffer: + * @data: the start of the buffer + * @size: the size of the buffer + * @msg: the result #GstSDPMessage + * + * Parse the contents of @size bytes pointed to by @data and store the result in + * @msg. + * + * Returns: #GST_SDP_OK on success. + */ +GstWFDResult +gst_wfd_message_parse_buffer (const guint8 * data, guint size, + GstWFDMessage * msg) +{ + gchar *p; + gchar buffer[255] = { 0 }; + guint idx = 0; + + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (data != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (size != 0, GST_WFD_EINVAL); + + p = (gchar *) data; + while (TRUE) { + + if (*p == '\0') + break; + + idx = 0; + while (*p != '\n' && *p != '\r' && *p != '\0') { + if (idx < sizeof (buffer) - 1) + buffer[idx++] = *p; + p++; + } + buffer[idx] = '\0'; + gst_wfd_parse_attribute (buffer, msg); + + if (*p == '\0') + break; + p += 2; + } + return GST_WFD_OK; +} + +/** + * gst_wfd_message_free: + * @msg: a #GstWFDMessage + * + * Free all resources allocated by @msg. @msg should not be used anymore after + * this function. This function should be used when @msg was dynamically + * allocated with gst_wfd_message_new(). + * + * Returns: a #GstWFDResult. + */ +GstWFDResult +gst_wfd_message_free (GstWFDMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + gst_wfd_message_uninit (msg); + g_free (msg); + + return GST_WFD_OK; +} + +/** + * gst_wfd_message_as_text: + * @msg: a #GstWFDMessage + * + * Convert the contents of @msg to a text string. + * + * Returns: A dynamically allocated string representing the WFD description. + */ +gchar * +gst_wfd_message_as_text (const GstWFDMessage * msg) +{ + /* change all vars so they match rfc? */ + GString *lines; + guint i; + + g_return_val_if_fail (msg != NULL, NULL); + + lines = g_string_new (""); + + /* list of audio codecs */ + if (msg->audio_codecs) { + g_string_append_printf (lines, GST_STRING_WFD_AUDIO_CODECS); + if (msg->audio_codecs->list) { + g_string_append_printf (lines, ":"); + for (i = 0; i < msg->audio_codecs->count; i++) { + g_string_append_printf (lines, " %s", + msg->audio_codecs->list[i].audio_format); + g_string_append_printf (lines, " %08x", + msg->audio_codecs->list[i].modes); + g_string_append_printf (lines, " %02x", + msg->audio_codecs->list[i].latency); + if ((i + 1) < msg->audio_codecs->count) + g_string_append_printf (lines, ","); + } + } + g_string_append_printf (lines, "\r\n"); + } + + /* list of video codecs */ + if (msg->video_formats) { + g_string_append_printf (lines, GST_STRING_WFD_VIDEO_FORMATS); + if (msg->video_formats->list) { + g_string_append_printf (lines, ":"); + g_string_append_printf (lines, " %02x", msg->video_formats->list->native); + g_string_append_printf (lines, " %02x", + msg->video_formats->list->preferred_display_mode_supported); + g_string_append_printf (lines, " %02x", + msg->video_formats->list->H264_codec.profile); + g_string_append_printf (lines, " %02x", + msg->video_formats->list->H264_codec.level); + g_string_append_printf (lines, " %08x", + msg->video_formats->list->H264_codec.misc_params.CEA_Support); + g_string_append_printf (lines, " %08x", + msg->video_formats->list->H264_codec.misc_params.VESA_Support); + g_string_append_printf (lines, " %08x", + msg->video_formats->list->H264_codec.misc_params.HH_Support); + g_string_append_printf (lines, " %02x", + msg->video_formats->list->H264_codec.misc_params.latency); + g_string_append_printf (lines, " %04x", + msg->video_formats->list->H264_codec.misc_params.min_slice_size); + g_string_append_printf (lines, " %04x", + msg->video_formats->list->H264_codec.misc_params.slice_enc_params); + g_string_append_printf (lines, " %02x", + msg->video_formats->list->H264_codec. + misc_params.frame_rate_control_support); + + if (msg->video_formats->list->H264_codec.max_hres) + g_string_append_printf (lines, " %04x", + msg->video_formats->list->H264_codec.max_hres); + else + g_string_append_printf (lines, " none"); + + if (msg->video_formats->list->H264_codec.max_vres) + g_string_append_printf (lines, " %04x", + msg->video_formats->list->H264_codec.max_vres); + else + g_string_append_printf (lines, " none"); + } + g_string_append_printf (lines, "\r\n"); + } + + /* list of video 3D codecs */ + if (msg->video_3d_formats) { + g_string_append_printf (lines, GST_STRING_WFD_3D_VIDEO_FORMATS); + g_string_append_printf (lines, ":"); + if (msg->video_3d_formats->list) { + g_string_append_printf (lines, " %02x", + msg->video_3d_formats->list->native); + g_string_append_printf (lines, " %02x", + msg->video_3d_formats->list->preferred_display_mode_supported); + g_string_append_printf (lines, " %02x", + msg->video_3d_formats->list->H264_codec.profile); + g_string_append_printf (lines, " %02x", + msg->video_3d_formats->list->H264_codec.level); + g_string_append_printf (lines, " %16x", + msg->video_3d_formats->list->H264_codec. + misc_params.video_3d_capability); + g_string_append_printf (lines, " %02x", + msg->video_3d_formats->list->H264_codec.misc_params.latency); + g_string_append_printf (lines, " %04x", + msg->video_3d_formats->list->H264_codec.misc_params.min_slice_size); + g_string_append_printf (lines, " %04x", + msg->video_3d_formats->list->H264_codec.misc_params.slice_enc_params); + g_string_append_printf (lines, " %02x", + msg->video_3d_formats->list->H264_codec. + misc_params.frame_rate_control_support); + if (msg->video_3d_formats->list->H264_codec.max_hres) + g_string_append_printf (lines, " %04x", + msg->video_3d_formats->list->H264_codec.max_hres); + else + g_string_append_printf (lines, " none"); + if (msg->video_3d_formats->list->H264_codec.max_vres) + g_string_append_printf (lines, " %04x", + msg->video_3d_formats->list->H264_codec.max_vres); + else + g_string_append_printf (lines, " none"); + } else { + g_string_append_printf (lines, " none"); + } + g_string_append_printf (lines, "\r\n"); + } + + if (msg->content_protection) { + g_string_append_printf (lines, GST_STRING_WFD_CONTENT_PROTECTION); + g_string_append_printf (lines, ":"); + if (msg->content_protection->hdcp2_spec) { + if (msg->content_protection->hdcp2_spec->hdcpversion) { + g_string_append_printf (lines, " %s", + msg->content_protection->hdcp2_spec->hdcpversion); + g_string_append_printf (lines, " %s", + msg->content_protection->hdcp2_spec->TCPPort); + } else { + g_string_append_printf (lines, " none"); + } + } else { + g_string_append_printf (lines, " none"); + } + g_string_append_printf (lines, "\r\n"); + } + + if (msg->display_edid) { + g_string_append_printf (lines, GST_STRING_WFD_DISPLAY_EDID); + g_string_append_printf (lines, ":"); + if (msg->display_edid->edid_supported) { + g_string_append_printf (lines, " %d", msg->display_edid->edid_supported); + if (msg->display_edid->edid_block_count) + g_string_append_printf (lines, " %d", + msg->display_edid->edid_block_count); + else + g_string_append_printf (lines, " none"); + } else { + g_string_append_printf (lines, " none"); + } + g_string_append_printf (lines, "\r\n"); + } + + if (msg->coupled_sink) { + g_string_append_printf (lines, GST_STRING_WFD_COUPLED_SINK); + g_string_append_printf (lines, ":"); + if (msg->coupled_sink->coupled_sink_cap) { + g_string_append_printf (lines, " %02x", + msg->coupled_sink->coupled_sink_cap->status); + if (msg->coupled_sink->coupled_sink_cap->sink_address) + g_string_append_printf (lines, " %s", + msg->coupled_sink->coupled_sink_cap->sink_address); + else + g_string_append_printf (lines, " none"); + } else { + g_string_append_printf (lines, " none"); + } + g_string_append_printf (lines, "\r\n"); + } + + if (msg->trigger_method) { + g_string_append_printf (lines, GST_STRING_WFD_TRIGGER_METHOD); + g_string_append_printf (lines, ":"); + g_string_append_printf (lines, " %s", + msg->trigger_method->wfd_trigger_method); + g_string_append_printf (lines, "\r\n"); + } + + if (msg->presentation_url) { + g_string_append_printf (lines, GST_STRING_WFD_PRESENTATION_URL); + g_string_append_printf (lines, ":"); + if (msg->presentation_url->wfd_url0) + g_string_append_printf (lines, " %s", msg->presentation_url->wfd_url0); + else + g_string_append_printf (lines, " none"); + if (msg->presentation_url->wfd_url1) + g_string_append_printf (lines, " %s", msg->presentation_url->wfd_url1); + else + g_string_append_printf (lines, " none"); + g_string_append_printf (lines, "\r\n"); + } + + if (msg->client_rtp_ports) { + g_string_append_printf (lines, GST_STRING_WFD_CLIENT_RTP_PORTS); + if (msg->client_rtp_ports->profile) { + g_string_append_printf (lines, ":"); + g_string_append_printf (lines, " %s", msg->client_rtp_ports->profile); + g_string_append_printf (lines, " %d", msg->client_rtp_ports->rtp_port0); + g_string_append_printf (lines, " %d", msg->client_rtp_ports->rtp_port1); + g_string_append_printf (lines, " %s", msg->client_rtp_ports->mode); + } + g_string_append_printf (lines, "\r\n"); + } + + if (msg->route) { + g_string_append_printf (lines, GST_STRING_WFD_ROUTE); + g_string_append_printf (lines, ":"); + g_string_append_printf (lines, " %s", msg->route->destination); + g_string_append_printf (lines, "\r\n"); + } + + if (msg->I2C) { + g_string_append_printf (lines, GST_STRING_WFD_I2C); + g_string_append_printf (lines, ":"); + if (msg->I2C->I2CPresent) + g_string_append_printf (lines, " %x", msg->I2C->I2C_port); + else + g_string_append_printf (lines, " none"); + g_string_append_printf (lines, "\r\n"); + } + + if (msg->av_format_change_timing) { + g_string_append_printf (lines, GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING); + g_string_append_printf (lines, ":"); + g_string_append_printf (lines, " %010llx", + msg->av_format_change_timing->PTS); + g_string_append_printf (lines, " %010llx", + msg->av_format_change_timing->DTS); + g_string_append_printf (lines, "\r\n"); + } + + if (msg->preferred_display_mode) { + g_string_append_printf (lines, GST_STRING_WFD_PREFERRED_DISPLAY_MODE); + g_string_append_printf (lines, ":"); + if (msg->preferred_display_mode->displaymodesupported) { + g_string_append_printf (lines, " %06llx", + msg->preferred_display_mode->p_clock); + g_string_append_printf (lines, " %04x", msg->preferred_display_mode->H); + g_string_append_printf (lines, " %04x", msg->preferred_display_mode->HB); + g_string_append_printf (lines, " %04x", + msg->preferred_display_mode->HSPOL_HSOFF); + g_string_append_printf (lines, " %04x", msg->preferred_display_mode->HSW); + g_string_append_printf (lines, " %04x", msg->preferred_display_mode->V); + g_string_append_printf (lines, " %04x", msg->preferred_display_mode->VB); + g_string_append_printf (lines, " %04x", + msg->preferred_display_mode->VSPOL_VSOFF); + g_string_append_printf (lines, " %04x", msg->preferred_display_mode->VSW); + g_string_append_printf (lines, " %02x", + msg->preferred_display_mode->VBS3D); + g_string_append_printf (lines, " %02x", + msg->preferred_display_mode->V2d_s3d_modes); + g_string_append_printf (lines, " %02x", + msg->preferred_display_mode->P_depth); + } else + g_string_append_printf (lines, " none"); + g_string_append_printf (lines, "\r\n"); + } + + if (msg->standby_resume_capability) { + g_string_append_printf (lines, GST_STRING_WFD_STANDBY_RESUME_CAPABILITY); + g_string_append_printf (lines, ":"); + if (msg->standby_resume_capability->standby_resume_cap) + g_string_append_printf (lines, " supported"); + else + g_string_append_printf (lines, " none"); + g_string_append_printf (lines, "\r\n"); + } + + if (msg->standby) { + g_string_append_printf (lines, GST_STRING_WFD_STANDBY); + g_string_append_printf (lines, "\r\n"); + } + + if (msg->connector_type) { + g_string_append_printf (lines, GST_STRING_WFD_CONNECTOR_TYPE); + g_string_append_printf (lines, ":"); + if (msg->connector_type->connector_type) + g_string_append_printf (lines, " %02x", + msg->connector_type->connector_type); + else + g_string_append_printf (lines, " none"); + g_string_append_printf (lines, "\r\n"); + } + + if (msg->idr_request) { + g_string_append_printf (lines, GST_STRING_WFD_IDR_REQUEST); + g_string_append_printf (lines, "\r\n"); + } + + return g_string_free (lines, FALSE); +} + +gchar * +gst_wfd_message_param_names_as_text (const GstWFDMessage * msg) +{ + /* change all vars so they match rfc? */ + GString *lines; + g_return_val_if_fail (msg != NULL, NULL); + + lines = g_string_new (""); + + /* list of audio codecs */ + if (msg->audio_codecs) { + g_string_append_printf (lines, GST_STRING_WFD_AUDIO_CODECS); + g_string_append_printf (lines, "\r\n"); + } + /* list of video codecs */ + if (msg->video_formats) { + g_string_append_printf (lines, GST_STRING_WFD_VIDEO_FORMATS); + g_string_append_printf (lines, "\r\n"); + } + /* list of video 3D codecs */ + if (msg->video_3d_formats) { + g_string_append_printf (lines, GST_STRING_WFD_3D_VIDEO_FORMATS); + g_string_append_printf (lines, "\r\n"); + } + if (msg->content_protection) { + g_string_append_printf (lines, GST_STRING_WFD_CONTENT_PROTECTION); + g_string_append_printf (lines, "\r\n"); + } + if (msg->display_edid) { + g_string_append_printf (lines, GST_STRING_WFD_DISPLAY_EDID); + g_string_append_printf (lines, "\r\n"); + } + if (msg->coupled_sink) { + g_string_append_printf (lines, GST_STRING_WFD_COUPLED_SINK); + g_string_append_printf (lines, "\r\n"); + } + if (msg->trigger_method) { + g_string_append_printf (lines, GST_STRING_WFD_TRIGGER_METHOD); + g_string_append_printf (lines, "\r\n"); + } + if (msg->presentation_url) { + g_string_append_printf (lines, GST_STRING_WFD_PRESENTATION_URL); + g_string_append_printf (lines, "\r\n"); + } + if (msg->client_rtp_ports) { + g_string_append_printf (lines, GST_STRING_WFD_CLIENT_RTP_PORTS); + g_string_append_printf (lines, "\r\n"); + } + if (msg->route) { + g_string_append_printf (lines, GST_STRING_WFD_ROUTE); + g_string_append_printf (lines, "\r\n"); + } + if (msg->I2C) { + g_string_append_printf (lines, GST_STRING_WFD_I2C); + g_string_append_printf (lines, "\r\n"); + } + if (msg->av_format_change_timing) { + g_string_append_printf (lines, GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING); + g_string_append_printf (lines, "\r\n"); + } + if (msg->preferred_display_mode) { + g_string_append_printf (lines, GST_STRING_WFD_PREFERRED_DISPLAY_MODE); + g_string_append_printf (lines, "\r\n"); + } + if (msg->standby_resume_capability) { + g_string_append_printf (lines, GST_STRING_WFD_STANDBY_RESUME_CAPABILITY); + g_string_append_printf (lines, "\r\n"); + } + if (msg->standby) { + g_string_append_printf (lines, GST_STRING_WFD_STANDBY); + g_string_append_printf (lines, "\r\n"); + } + if (msg->connector_type) { + g_string_append_printf (lines, GST_STRING_WFD_CONNECTOR_TYPE); + g_string_append_printf (lines, "\r\n"); + } + if (msg->idr_request) { + g_string_append_printf (lines, GST_STRING_WFD_IDR_REQUEST); + g_string_append_printf (lines, "\r\n"); + } + + return g_string_free (lines, FALSE); +} + +/** + * gst_wfd_message_dump: + * @msg: a #GstWFDMessage + * + * Dump the parsed contents of @msg to stdout. + * + * Returns: a #GstWFDResult. + */ +GstWFDResult +gst_wfd_message_dump (const GstWFDMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (msg->audio_codecs) { + guint i = 0; + g_print ("Audio supported formats : \n"); + for (; i < msg->audio_codecs->count; i++) { + g_print ("Codec: %s\n", msg->audio_codecs->list[i].audio_format); + if (!strcmp (msg->audio_codecs->list[i].audio_format, "LPCM")) { + if (msg->audio_codecs->list[i].modes & GST_WFD_FREQ_44100) + g_print (" Freq: %d\n", 44100); + if (msg->audio_codecs->list[i].modes & GST_WFD_FREQ_48000) + g_print (" Freq: %d\n", 48000); + g_print (" Channels: %d\n", 2); + } + if (!strcmp (msg->audio_codecs->list[i].audio_format, "AAC")) { + g_print (" Freq: %d\n", 48000); + if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_2) + g_print (" Channels: %d\n", 2); + if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_4) + g_print (" Channels: %d\n", 4); + if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_6) + g_print (" Channels: %d\n", 6); + if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_8) + g_print (" Channels: %d\n", 8); + } + if (!strcmp (msg->audio_codecs->list[i].audio_format, "AC3")) { + g_print (" Freq: %d\n", 48000); + if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_2) + g_print (" Channels: %d\n", 2); + if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_4) + g_print (" Channels: %d\n", 4); + if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_6) + g_print (" Channels: %d\n", 6); + } + g_print (" Bitwidth: %d\n", 16); + g_print (" Latency: %d\n", msg->audio_codecs->list[i].latency); + } + } + + + if (msg->video_formats) { + g_print ("Video supported formats : \n"); + if (msg->video_formats->list) { + guint nativeindex = 0; + g_print ("Codec: H264\n"); + if ((msg->video_formats->list->native & 0x7) == + GST_WFD_VIDEO_CEA_RESOLUTION) { + g_print (" Native type: CEA\n"); + } else if ((msg->video_formats->list->native & 0x7) == + GST_WFD_VIDEO_VESA_RESOLUTION) { + g_print (" Native type: VESA\n"); + } else if ((msg->video_formats->list->native & 0x7) == + GST_WFD_VIDEO_HH_RESOLUTION) { + g_print (" Native type: HH\n"); + } + nativeindex = msg->video_formats->list->native >> 3; + g_print (" Resolution: %d\n", (1 << nativeindex)); + + if (msg->video_formats->list-> + H264_codec.profile & GST_WFD_H264_BASE_PROFILE) { + g_print (" Profile: BASE\n"); + } else if (msg->video_formats->list-> + H264_codec.profile & GST_WFD_H264_HIGH_PROFILE) { + g_print (" Profile: HIGH\n"); + } + if (msg->video_formats->list->H264_codec.level & GST_WFD_H264_LEVEL_3_1) { + g_print (" Level: 3.1\n"); + } else if (msg->video_formats->list-> + H264_codec.level & GST_WFD_H264_LEVEL_3_2) { + g_print (" Level: 3.2\n"); + } else if (msg->video_formats->list-> + H264_codec.level & GST_WFD_H264_LEVEL_4) { + g_print (" Level: 4\n"); + } else if (msg->video_formats->list-> + H264_codec.level & GST_WFD_H264_LEVEL_4_1) { + g_print (" Level: 4.1\n"); + } else if (msg->video_formats->list-> + H264_codec.level & GST_WFD_H264_LEVEL_4_2) { + g_print (" Level: 4.2\n"); + } + g_print (" Latency: %d\n", + msg->video_formats->list->H264_codec.misc_params.latency); + g_print (" min_slice_size: %x\n", + msg->video_formats->list->H264_codec.misc_params.min_slice_size); + g_print (" slice_enc_params: %x\n", + msg->video_formats->list->H264_codec.misc_params.slice_enc_params); + g_print (" frame_rate_control_support: %x\n", + msg->video_formats->list->H264_codec. + misc_params.frame_rate_control_support); + if (msg->video_formats->list->H264_codec.max_hres) { + g_print (" Max Height: %04d\n", + msg->video_formats->list->H264_codec.max_hres); + } + if (msg->video_formats->list->H264_codec.max_vres) { + g_print (" Max Width: %04d\n", + msg->video_formats->list->H264_codec.max_vres); + } + } + } + + if (msg->video_3d_formats) { + g_print ("wfd_3d_formats"); + g_print ("\r\n"); + } + + if (msg->content_protection) { + g_print (GST_STRING_WFD_CONTENT_PROTECTION); + g_print ("\r\n"); + } + + if (msg->display_edid) { + g_print (GST_STRING_WFD_DISPLAY_EDID); + g_print ("\r\n"); + } + + if (msg->coupled_sink) { + g_print (GST_STRING_WFD_COUPLED_SINK); + g_print ("\r\n"); + } + + if (msg->trigger_method) { + g_print (" Trigger type: %s\n", msg->trigger_method->wfd_trigger_method); + } + + if (msg->presentation_url) { + g_print (GST_STRING_WFD_PRESENTATION_URL); + g_print ("\r\n"); + } + + if (msg->client_rtp_ports) { + g_print (" Client RTP Ports : \n"); + if (msg->client_rtp_ports->profile) { + g_print ("%s\n", msg->client_rtp_ports->profile); + g_print (" %d\n", msg->client_rtp_ports->rtp_port0); + g_print (" %d\n", msg->client_rtp_ports->rtp_port1); + g_print (" %s\n", msg->client_rtp_ports->mode); + } + g_print ("\r\n"); + } + + if (msg->route) { + g_print (GST_STRING_WFD_ROUTE); + g_print ("\r\n"); + } + + if (msg->I2C) { + g_print (GST_STRING_WFD_I2C); + g_print ("\r\n"); + } + + if (msg->av_format_change_timing) { + g_print (GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING); + g_print ("\r\n"); + } + + if (msg->preferred_display_mode) { + g_print (GST_STRING_WFD_PREFERRED_DISPLAY_MODE); + g_print ("\r\n"); + } + + if (msg->standby_resume_capability) { + g_print (GST_STRING_WFD_STANDBY_RESUME_CAPABILITY); + g_print ("\r\n"); + } + + if (msg->standby) { + g_print (GST_STRING_WFD_STANDBY); + g_print ("\r\n"); + } + + if (msg->connector_type) { + g_print (GST_STRING_WFD_CONNECTOR_TYPE); + g_print ("\r\n"); + } + + if (msg->idr_request) { + g_print (GST_STRING_WFD_IDR_REQUEST); + g_print ("\r\n"); + } + + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_set_supported_audio_format (GstWFDMessage * msg, + GstWFDAudioFormats a_codec, + guint a_freq, guint a_channels, guint a_bitwidth, guint32 a_latency) +{ + guint temp = a_codec; + guint i = 0; + guint pcm = 0, aac = 0, ac3 = 0; + + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->audio_codecs) + msg->audio_codecs = g_new0 (GstWFDAudioCodeclist, 1); + + if (a_codec != GST_WFD_AUDIO_UNKNOWN) { + while (temp) { + msg->audio_codecs->count++; + temp >>= 1; + } + msg->audio_codecs->list = + g_new0 (GstWFDAudioCodec, msg->audio_codecs->count); + for (; i < msg->audio_codecs->count; i++) { + if ((a_codec & GST_WFD_AUDIO_LPCM) && (!pcm)) { + msg->audio_codecs->list[i].audio_format = g_strdup ("LPCM"); + msg->audio_codecs->list[i].modes = a_freq; + msg->audio_codecs->list[i].latency = a_latency; + pcm = 1; + } else if ((a_codec & GST_WFD_AUDIO_AAC) && (!aac)) { + msg->audio_codecs->list[i].audio_format = g_strdup ("AAC"); + msg->audio_codecs->list[i].modes = a_channels; + msg->audio_codecs->list[i].latency = a_latency; + aac = 1; + } else if ((a_codec & GST_WFD_AUDIO_AC3) && (!ac3)) { + msg->audio_codecs->list[i].audio_format = g_strdup ("AC3"); + msg->audio_codecs->list[i].modes = a_channels; + msg->audio_codecs->list[i].latency = a_latency; + ac3 = 1; + } + } + } + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_set_prefered_audio_format (GstWFDMessage * msg, + GstWFDAudioFormats a_codec, + GstWFDAudioFreq a_freq, + GstWFDAudioChannels a_channels, guint a_bitwidth, guint32 a_latency) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->audio_codecs) + msg->audio_codecs = g_new0 (GstWFDAudioCodeclist, 1); + + msg->audio_codecs->list = g_new0 (GstWFDAudioCodec, 1); + msg->audio_codecs->count = 1; + if (a_codec == GST_WFD_AUDIO_LPCM) { + msg->audio_codecs->list->audio_format = g_strdup ("LPCM"); + msg->audio_codecs->list->modes = a_freq; + msg->audio_codecs->list->latency = a_latency; + } else if (a_codec == GST_WFD_AUDIO_AAC) { + msg->audio_codecs->list->audio_format = g_strdup ("AAC"); + msg->audio_codecs->list->modes = a_channels; + msg->audio_codecs->list->latency = a_latency; + } else if (a_codec == GST_WFD_AUDIO_AC3) { + msg->audio_codecs->list->audio_format = g_strdup ("AC3"); + msg->audio_codecs->list->modes = a_channels; + msg->audio_codecs->list->latency = a_latency; + } + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_supported_audio_format (GstWFDMessage * msg, + guint * a_codec, + guint * a_freq, guint * a_channels, guint * a_bitwidth, guint32 * a_latency) +{ + guint i = 0; + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (msg->audio_codecs != NULL, GST_WFD_EINVAL); + + for (; i < msg->audio_codecs->count; i++) { + if (!g_strcmp0 (msg->audio_codecs->list[i].audio_format, "LPCM")) { + *a_codec |= GST_WFD_AUDIO_LPCM; + *a_freq |= msg->audio_codecs->list[i].modes; + *a_channels |= GST_WFD_CHANNEL_2; + *a_bitwidth = 16; + *a_latency = msg->audio_codecs->list[i].latency; + } else if (!g_strcmp0 (msg->audio_codecs->list[i].audio_format, "AAC")) { + *a_codec |= GST_WFD_AUDIO_AAC; + *a_freq |= GST_WFD_FREQ_48000; + *a_channels |= msg->audio_codecs->list[i].modes; + *a_bitwidth = 16; + *a_latency = msg->audio_codecs->list[i].latency; + } else if (!g_strcmp0 (msg->audio_codecs->list[i].audio_format, "AC3")) { + *a_codec |= GST_WFD_AUDIO_AC3; + *a_freq |= GST_WFD_FREQ_48000; + *a_channels |= msg->audio_codecs->list[i].modes; + *a_bitwidth = 16; + *a_latency = msg->audio_codecs->list[i].latency; + } + } + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_prefered_audio_format (GstWFDMessage * msg, + GstWFDAudioFormats * a_codec, + GstWFDAudioFreq * a_freq, + GstWFDAudioChannels * a_channels, guint * a_bitwidth, guint32 * a_latency) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!g_strcmp0 (msg->audio_codecs->list->audio_format, "LPCM")) { + *a_codec = GST_WFD_AUDIO_LPCM; + *a_freq = msg->audio_codecs->list->modes; + *a_channels = GST_WFD_CHANNEL_2; + *a_bitwidth = 16; + *a_latency = msg->audio_codecs->list->latency; + } else if (!g_strcmp0 (msg->audio_codecs->list->audio_format, "AAC")) { + *a_codec = GST_WFD_AUDIO_AAC; + *a_freq = GST_WFD_FREQ_48000; + *a_channels = msg->audio_codecs->list->modes; + *a_bitwidth = 16; + *a_latency = msg->audio_codecs->list->latency; + } else if (!g_strcmp0 (msg->audio_codecs->list->audio_format, "AC3")) { + *a_codec = GST_WFD_AUDIO_AC3; + *a_freq = GST_WFD_FREQ_48000; + *a_channels = msg->audio_codecs->list->modes; + *a_bitwidth = 16; + *a_latency = msg->audio_codecs->list->latency; + } + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_set_supported_video_format (GstWFDMessage * msg, + GstWFDVideoCodecs v_codec, + GstWFDVideoNativeResolution v_native, + guint64 v_native_resolution, + guint64 v_cea_resolution, + guint64 v_vesa_resolution, + guint64 v_hh_resolution, + guint v_profile, + guint v_level, + guint32 v_latency, + guint32 v_max_height, + guint32 v_max_width, + guint32 min_slice_size, guint32 slice_enc_params, guint frame_rate_control) +{ + guint nativeindex = 0; + guint64 temp = v_native_resolution; + + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->video_formats) + msg->video_formats = g_new0 (GstWFDVideoCodeclist, 1); + + if (v_codec != GST_WFD_VIDEO_UNKNOWN) { + msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1); + while (temp) { + nativeindex++; + temp >>= 1; + } + + msg->video_formats->list->native = nativeindex - 1; + msg->video_formats->list->native <<= 3; + + if (v_native == GST_WFD_VIDEO_VESA_RESOLUTION) + msg->video_formats->list->native |= 1; + else if (v_native == GST_WFD_VIDEO_HH_RESOLUTION) + msg->video_formats->list->native |= 2; + + msg->video_formats->list->preferred_display_mode_supported = 1; + msg->video_formats->list->H264_codec.profile = v_profile; + msg->video_formats->list->H264_codec.level = v_level; + msg->video_formats->list->H264_codec.max_hres = v_max_height; + msg->video_formats->list->H264_codec.max_vres = v_max_width; + msg->video_formats->list->H264_codec.misc_params.CEA_Support = + v_cea_resolution; + msg->video_formats->list->H264_codec.misc_params.VESA_Support = + v_vesa_resolution; + msg->video_formats->list->H264_codec.misc_params.HH_Support = + v_hh_resolution; + msg->video_formats->list->H264_codec.misc_params.latency = v_latency; + msg->video_formats->list->H264_codec.misc_params.min_slice_size = + min_slice_size; + msg->video_formats->list->H264_codec.misc_params.slice_enc_params = + slice_enc_params; + msg->video_formats->list->H264_codec. + misc_params.frame_rate_control_support = frame_rate_control; + } + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_set_prefered_video_format (GstWFDMessage * msg, + GstWFDVideoCodecs v_codec, + GstWFDVideoNativeResolution v_native, + guint64 v_native_resolution, + GstWFDVideoCEAResolution v_cea_resolution, + GstWFDVideoVESAResolution v_vesa_resolution, + GstWFDVideoHHResolution v_hh_resolution, + GstWFDVideoH264Profile v_profile, + GstWFDVideoH264Level v_level, + guint32 v_latency, + guint32 v_max_height, + guint32 v_max_width, + guint32 min_slice_size, guint32 slice_enc_params, guint frame_rate_control) +{ + guint nativeindex = 0; + guint64 temp = v_native_resolution; + + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->video_formats) + msg->video_formats = g_new0 (GstWFDVideoCodeclist, 1); + msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1); + + while (temp) { + nativeindex++; + temp >>= 1; + } + + if (nativeindex) + msg->video_formats->list->native = nativeindex - 1; + msg->video_formats->list->native <<= 3; + + if (v_native == GST_WFD_VIDEO_VESA_RESOLUTION) + msg->video_formats->list->native |= 1; + else if (v_native == GST_WFD_VIDEO_HH_RESOLUTION) + msg->video_formats->list->native |= 2; + + msg->video_formats->list->preferred_display_mode_supported = 0; + msg->video_formats->list->H264_codec.profile = v_profile; + msg->video_formats->list->H264_codec.level = v_level; + msg->video_formats->list->H264_codec.max_hres = v_max_height; + msg->video_formats->list->H264_codec.max_vres = v_max_width; + msg->video_formats->list->H264_codec.misc_params.CEA_Support = + v_cea_resolution; + msg->video_formats->list->H264_codec.misc_params.VESA_Support = + v_vesa_resolution; + msg->video_formats->list->H264_codec.misc_params.HH_Support = v_hh_resolution; + msg->video_formats->list->H264_codec.misc_params.latency = v_latency; + msg->video_formats->list->H264_codec.misc_params.min_slice_size = + min_slice_size; + msg->video_formats->list->H264_codec.misc_params.slice_enc_params = + slice_enc_params; + msg->video_formats->list->H264_codec.misc_params.frame_rate_control_support = + frame_rate_control; + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_supported_video_format (GstWFDMessage * msg, + GstWFDVideoCodecs * v_codec, + GstWFDVideoNativeResolution * v_native, + guint64 * v_native_resolution, + guint64 * v_cea_resolution, + guint64 * v_vesa_resolution, + guint64 * v_hh_resolution, + guint * v_profile, + guint * v_level, + guint32 * v_latency, + guint32 * v_max_height, + guint32 * v_max_width, + guint32 * min_slice_size, + guint32 * slice_enc_params, guint * frame_rate_control) +{ + guint nativeindex = 0; + + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + *v_codec = GST_WFD_VIDEO_H264; + *v_native = msg->video_formats->list->native & 0x7; + nativeindex = msg->video_formats->list->native >> 3; + *v_native_resolution = ((guint64) 1) << nativeindex; + *v_profile = msg->video_formats->list->H264_codec.profile; + *v_level = msg->video_formats->list->H264_codec.level; + *v_max_height = msg->video_formats->list->H264_codec.max_hres; + *v_max_width = msg->video_formats->list->H264_codec.max_vres; + *v_cea_resolution = + msg->video_formats->list->H264_codec.misc_params.CEA_Support; + *v_vesa_resolution = + msg->video_formats->list->H264_codec.misc_params.VESA_Support; + *v_hh_resolution = + msg->video_formats->list->H264_codec.misc_params.HH_Support; + *v_latency = msg->video_formats->list->H264_codec.misc_params.latency; + *min_slice_size = + msg->video_formats->list->H264_codec.misc_params.min_slice_size; + *slice_enc_params = + msg->video_formats->list->H264_codec.misc_params.slice_enc_params; + *frame_rate_control = + msg->video_formats->list->H264_codec. + misc_params.frame_rate_control_support; + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_prefered_video_format (GstWFDMessage * msg, + GstWFDVideoCodecs * v_codec, + GstWFDVideoNativeResolution * v_native, + guint64 * v_native_resolution, + GstWFDVideoCEAResolution * v_cea_resolution, + GstWFDVideoVESAResolution * v_vesa_resolution, + GstWFDVideoHHResolution * v_hh_resolution, + GstWFDVideoH264Profile * v_profile, + GstWFDVideoH264Level * v_level, + guint32 * v_latency, + guint32 * v_max_height, + guint32 * v_max_width, + guint32 * min_slice_size, + guint32 * slice_enc_params, guint * frame_rate_control) +{ + guint nativeindex = 0; + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + *v_codec = GST_WFD_VIDEO_H264; + *v_native = msg->video_formats->list->native & 0x7; + nativeindex = msg->video_formats->list->native >> 3; + *v_native_resolution = ((guint64) 1) << nativeindex; + *v_profile = msg->video_formats->list->H264_codec.profile; + *v_level = msg->video_formats->list->H264_codec.level; + *v_max_height = msg->video_formats->list->H264_codec.max_hres; + *v_max_width = msg->video_formats->list->H264_codec.max_vres; + *v_cea_resolution = + msg->video_formats->list->H264_codec.misc_params.CEA_Support; + *v_vesa_resolution = + msg->video_formats->list->H264_codec.misc_params.VESA_Support; + *v_hh_resolution = + msg->video_formats->list->H264_codec.misc_params.HH_Support; + *v_latency = msg->video_formats->list->H264_codec.misc_params.latency; + *min_slice_size = + msg->video_formats->list->H264_codec.misc_params.min_slice_size; + *slice_enc_params = + msg->video_formats->list->H264_codec.misc_params.slice_enc_params; + *frame_rate_control = + msg->video_formats->list->H264_codec. + misc_params.frame_rate_control_support; + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_set_display_edid (GstWFDMessage * msg, + gboolean edid_supported, guint32 edid_blockcount, gchar * edid_playload) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + if (!msg->display_edid) + msg->display_edid = g_new0 (GstWFDDisplayEdid, 1); + msg->display_edid->edid_supported = edid_supported; + if (!edid_supported) + return GST_WFD_OK; + msg->display_edid->edid_block_count = edid_blockcount; + if (edid_blockcount) { + msg->display_edid->edid_payload = g_malloc (128 * edid_blockcount); + if (!msg->display_edid->edid_payload) + memcpy (msg->display_edid->edid_payload, edid_playload, + 128 * edid_blockcount); + } else + msg->display_edid->edid_payload = g_strdup ("none"); + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_display_edid (GstWFDMessage * msg, + gboolean * edid_supported, + guint32 * edid_blockcount, gchar ** edid_playload) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + if (msg->display_edid) { + if (msg->display_edid->edid_supported) { + *edid_blockcount = msg->display_edid->edid_block_count; + if (msg->display_edid->edid_block_count) { + char *temp; + temp = g_malloc (EDID_BLOCK_SIZE * msg->display_edid->edid_block_count); + if (temp) { + memset (temp, 0, + EDID_BLOCK_SIZE * msg->display_edid->edid_block_count); + memcpy (temp, msg->display_edid->edid_payload, + EDID_BLOCK_SIZE * msg->display_edid->edid_block_count); + *edid_playload = temp; + *edid_supported = TRUE; + } + } else + *edid_playload = g_strdup ("none"); + } + } else + *edid_supported = FALSE; + return GST_WFD_OK; +} + + +GstWFDResult +gst_wfd_message_set_contentprotection_type (GstWFDMessage * msg, + GstWFDHDCPProtection hdcpversion, guint32 TCPPort) +{ + char str[11] = { 0, }; + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->content_protection) + msg->content_protection = g_new0 (GstWFDContentProtection, 1); + if (hdcpversion == GST_WFD_HDCP_NONE) + return GST_WFD_OK; + msg->content_protection->hdcp2_spec = g_new0 (GstWFDHdcp2Spec, 1); + if (hdcpversion == GST_WFD_HDCP_2_0) + msg->content_protection->hdcp2_spec->hdcpversion = g_strdup ("HDCP2.0"); + else if (hdcpversion == GST_WFD_HDCP_2_1) + msg->content_protection->hdcp2_spec->hdcpversion = g_strdup ("HDCP2.1"); + snprintf (str, sizeof (str), "port=%d", TCPPort); + msg->content_protection->hdcp2_spec->TCPPort = g_strdup (str); + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_contentprotection_type (GstWFDMessage * msg, + GstWFDHDCPProtection * hdcpversion, guint32 * TCPPort) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + if (msg->content_protection && msg->content_protection->hdcp2_spec) { + char *result = NULL; + char *ptr = NULL; + if (!g_strcmp0 (msg->content_protection->hdcp2_spec->hdcpversion, "none")) { + *hdcpversion = GST_WFD_HDCP_NONE; + *TCPPort = 0; + return GST_WFD_OK; + } + if (!g_strcmp0 (msg->content_protection->hdcp2_spec->hdcpversion, + "HDCP2.0")) + *hdcpversion = GST_WFD_HDCP_2_0; + else if (!g_strcmp0 (msg->content_protection->hdcp2_spec->hdcpversion, + "HDCP2.1")) + *hdcpversion = GST_WFD_HDCP_2_1; + else { + *hdcpversion = GST_WFD_HDCP_NONE; + *TCPPort = 0; + return GST_WFD_OK; + } + + result = strtok_r (msg->content_protection->hdcp2_spec->TCPPort, "=", &ptr); + while (result != NULL) { + result = strtok_r (NULL, "=", &ptr); + *TCPPort = atoi (result); + break; + } + } else + *hdcpversion = GST_WFD_HDCP_NONE; + return GST_WFD_OK; +} + + +GstWFDResult +gst_wfd_messge_set_prefered_rtp_ports (GstWFDMessage * msg, + GstWFDRTSPTransMode trans, + GstWFDRTSPProfile profile, + GstWFDRTSPLowerTrans lowertrans, guint32 rtp_port0, guint32 rtp_port1) +{ + GString *lines; + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->client_rtp_ports) + msg->client_rtp_ports = g_new0 (GstWFDClientRtpPorts, 1); + + if (trans != GST_WFD_RTSP_TRANS_UNKNOWN) { + lines = g_string_new (""); + if (trans == GST_WFD_RTSP_TRANS_RTP) + g_string_append_printf (lines, "RTP"); + else if (trans == GST_WFD_RTSP_TRANS_RDT) + g_string_append_printf (lines, "RDT"); + + if (profile == GST_WFD_RTSP_PROFILE_AVP) + g_string_append_printf (lines, "/AVP"); + else if (profile == GST_WFD_RTSP_PROFILE_SAVP) + g_string_append_printf (lines, "/SAVP"); + + if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_UDP) + g_string_append_printf (lines, "/UDP;unicast"); + else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST) + g_string_append_printf (lines, "/UDP;multicast"); + else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_TCP) + g_string_append_printf (lines, "/TCP;unicast"); + else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_HTTP) + g_string_append_printf (lines, "/HTTP"); + + msg->client_rtp_ports->profile = g_string_free (lines, FALSE); + msg->client_rtp_ports->rtp_port0 = rtp_port0; + msg->client_rtp_ports->rtp_port1 = rtp_port1; + msg->client_rtp_ports->mode = g_strdup ("mode=play"); + } + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_prefered_rtp_ports (GstWFDMessage * msg, + GstWFDRTSPTransMode * trans, + GstWFDRTSPProfile * profile, + GstWFDRTSPLowerTrans * lowertrans, guint32 * rtp_port0, guint32 * rtp_port1) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (msg->client_rtp_ports != NULL, GST_WFD_EINVAL); + + if (g_strrstr (msg->client_rtp_ports->profile, "RTP")) + *trans = GST_WFD_RTSP_TRANS_RTP; + if (g_strrstr (msg->client_rtp_ports->profile, "RDT")) + *trans = GST_WFD_RTSP_TRANS_RDT; + if (g_strrstr (msg->client_rtp_ports->profile, "AVP")) + *profile = GST_WFD_RTSP_PROFILE_AVP; + if (g_strrstr (msg->client_rtp_ports->profile, "SAVP")) + *profile = GST_WFD_RTSP_PROFILE_SAVP; + if (g_strrstr (msg->client_rtp_ports->profile, "UDP;unicast")) + *lowertrans = GST_WFD_RTSP_LOWER_TRANS_UDP; + if (g_strrstr (msg->client_rtp_ports->profile, "UDP;multicast")) + *lowertrans = GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST; + if (g_strrstr (msg->client_rtp_ports->profile, "TCP;unicast")) + *lowertrans = GST_WFD_RTSP_LOWER_TRANS_TCP; + if (g_strrstr (msg->client_rtp_ports->profile, "HTTP")) + *lowertrans = GST_WFD_RTSP_LOWER_TRANS_HTTP; + + *rtp_port0 = msg->client_rtp_ports->rtp_port0; + *rtp_port1 = msg->client_rtp_ports->rtp_port1; + + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_set_presentation_url (GstWFDMessage * msg, gchar * wfd_url0, + gchar * wfd_url1) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->presentation_url) + msg->presentation_url = g_new0 (GstWFDPresentationUrl, 1); + if (wfd_url0) + msg->presentation_url->wfd_url0 = g_strdup (wfd_url0); + if (wfd_url1) + msg->presentation_url->wfd_url1 = g_strdup (wfd_url1); + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_presentation_url (GstWFDMessage * msg, gchar ** wfd_url0, + gchar ** wfd_url1) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (msg->presentation_url) { + *wfd_url0 = g_strdup (msg->presentation_url->wfd_url0); + *wfd_url1 = g_strdup (msg->presentation_url->wfd_url1); + } + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_set_av_format_change_timing(GstWFDMessage *msg, guint64 PTS, guint64 DTS) +{ + g_return_val_if_fail(msg != NULL, GST_WFD_EINVAL); + + if (!msg->av_format_change_timing) + msg->av_format_change_timing = g_new0(GstWFDAVFormatChangeTiming, 1); + + msg->av_format_change_timing->PTS = PTS; + msg->av_format_change_timing->DTS = DTS; + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_av_format_change_timing(GstWFDMessage *msg, guint64 *PTS, guint64 *DTS) +{ + g_return_val_if_fail(msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail(PTS != NULL, GST_WFD_EINVAL); + g_return_val_if_fail(DTS != NULL, GST_WFD_EINVAL); + + if (msg->av_format_change_timing) { + *PTS = msg->av_format_change_timing->PTS; + *DTS = msg->av_format_change_timing->DTS; + } + + return GST_WFD_OK; +} diff --git a/gst/rtsp-server/gstwfdmessage.h b/gst/rtsp-server/gstwfdmessage.h new file mode 100755 index 0000000..3261289 --- /dev/null +++ b/gst/rtsp-server/gstwfdmessage.h @@ -0,0 +1,618 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * 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. + */ +/* + * Unless otherwise indicated, Source Code is licensed under MIT license. + * See further explanation attached in License Statement (distributed in the file + * LICENSE). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __GST_WFD_MESSAGE_H__ +#define __GST_WFD_MESSAGE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_STRING_WFD_AUDIO_CODECS "wfd_audio_codecs" +#define GST_STRING_WFD_VIDEO_FORMATS "wfd_video_formats" +#define GST_STRING_WFD_3D_VIDEO_FORMATS "wfd_3d_video_formats" +#define GST_STRING_WFD_CONTENT_PROTECTION "wfd_content_protection" +#define GST_STRING_WFD_DISPLAY_EDID "wfd_display_edid" +#define GST_STRING_WFD_COUPLED_SINK "wfd_coupled_sink" +#define GST_STRING_WFD_TRIGGER_METHOD "wfd_trigger_method" +#define GST_STRING_WFD_PRESENTATION_URL "wfd_presentation_URL" +#define GST_STRING_WFD_CLIENT_RTP_PORTS "wfd_client_rtp_ports" +#define GST_STRING_WFD_ROUTE "wfd_route" +#define GST_STRING_WFD_I2C "wfd_I2C" +#define GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING "wfd_av_format_change_timing" +#define GST_STRING_WFD_PREFERRED_DISPLAY_MODE "wfd_preferred_display_mode" +#define GST_STRING_WFD_STANDBY_RESUME_CAPABILITY "wfd_standby_resume_capability" +#define GST_STRING_WFD_STANDBY "wfd_standby" +#define GST_STRING_WFD_CONNECTOR_TYPE "wfd_connector_type" +#define GST_STRING_WFD_IDR_REQUEST "wfd_idr_request" + +/** + * GstWFDResult: + * @GST_WFD_OK: A successful return value + * @GST_WFD_EINVAL: a function was given invalid parameters + * + * Return values for the WFD functions. + */ +typedef enum { + GST_WFD_OK = 0, + GST_WFD_EINVAL = -1 +} GstWFDResult; + + +typedef enum { + GST_WFD_AUDIO_UNKNOWN = 0, + GST_WFD_AUDIO_LPCM = (1 << 0), + GST_WFD_AUDIO_AAC = (1 << 1), + GST_WFD_AUDIO_AC3 = (1 << 2) +} GstWFDAudioFormats; + +typedef enum { + GST_WFD_FREQ_UNKNOWN = 0, + GST_WFD_FREQ_44100 = (1 << 0), + GST_WFD_FREQ_48000 = (1 << 1) +} GstWFDAudioFreq; + +typedef enum { + GST_WFD_CHANNEL_UNKNOWN = 0, + GST_WFD_CHANNEL_2 = (1 << 0), + GST_WFD_CHANNEL_4 = (1 << 1), + GST_WFD_CHANNEL_6 = (1 << 2), + GST_WFD_CHANNEL_8 = (1 << 3) +} GstWFDAudioChannels; + + +typedef enum { + GST_WFD_VIDEO_UNKNOWN = 0, + GST_WFD_VIDEO_H264 = (1 << 0) +} GstWFDVideoCodecs; + +typedef enum { + GST_WFD_VIDEO_CEA_RESOLUTION = 0, + GST_WFD_VIDEO_VESA_RESOLUTION, + GST_WFD_VIDEO_HH_RESOLUTION +} GstWFDVideoNativeResolution; + +typedef enum { + GST_WFD_CEA_UNKNOWN = 0, + GST_WFD_CEA_640x480P60 = (1 << 0), + GST_WFD_CEA_720x480P60 = (1 << 1), + GST_WFD_CEA_720x480I60 = (1 << 2), + GST_WFD_CEA_720x576P50 = (1 << 3), + GST_WFD_CEA_720x576I50 = (1 << 4), + GST_WFD_CEA_1280x720P30 = (1 << 5), + GST_WFD_CEA_1280x720P60 = (1 << 6), + GST_WFD_CEA_1920x1080P30= (1 << 7), + GST_WFD_CEA_1920x1080P60= (1 << 8), + GST_WFD_CEA_1920x1080I60= (1 << 9), + GST_WFD_CEA_1280x720P25 = (1 << 10), + GST_WFD_CEA_1280x720P50 = (1 << 11), + GST_WFD_CEA_1920x1080P25= (1 << 12), + GST_WFD_CEA_1920x1080P50= (1 << 13), + GST_WFD_CEA_1920x1080I50= (1 << 14), + GST_WFD_CEA_1280x720P24 = (1 << 15), + GST_WFD_CEA_1920x1080P24= (1 << 16) +} GstWFDVideoCEAResolution; + +typedef enum { + GST_WFD_VESA_UNKNOWN = 0, + GST_WFD_VESA_800x600P30 = (1 << 0), + GST_WFD_VESA_800x600P60 = (1 << 1), + GST_WFD_VESA_1024x768P30 = (1 << 2), + GST_WFD_VESA_1024x768P60 = (1 << 3), + GST_WFD_VESA_1152x864P30 = (1 << 4), + GST_WFD_VESA_1152x864P60 = (1 << 5), + GST_WFD_VESA_1280x768P30 = (1 << 6), + GST_WFD_VESA_1280x768P60 = (1 << 7), + GST_WFD_VESA_1280x800P30 = (1 << 8), + GST_WFD_VESA_1280x800P60 = (1 << 9), + GST_WFD_VESA_1360x768P30 = (1 << 10), + GST_WFD_VESA_1360x768P60 = (1 << 11), + GST_WFD_VESA_1366x768P30 = (1 << 12), + GST_WFD_VESA_1366x768P60 = (1 << 13), + GST_WFD_VESA_1280x1024P30 = (1 << 14), + GST_WFD_VESA_1280x1024P60 = (1 << 15), + GST_WFD_VESA_1400x1050P30 = (1 << 16), + GST_WFD_VESA_1400x1050P60 = (1 << 17), + GST_WFD_VESA_1440x900P30 = (1 << 18), + GST_WFD_VESA_1440x900P60 = (1 << 19), + GST_WFD_VESA_1600x900P30 = (1 << 20), + GST_WFD_VESA_1600x900P60 = (1 << 21), + GST_WFD_VESA_1600x1200P30 = (1 << 22), + GST_WFD_VESA_1600x1200P60 = (1 << 23), + GST_WFD_VESA_1680x1024P30 = (1 << 24), + GST_WFD_VESA_1680x1024P60 = (1 << 25), + GST_WFD_VESA_1680x1050P30 = (1 << 26), + GST_WFD_VESA_1680x1050P60 = (1 << 27), + GST_WFD_VESA_1920x1200P30 = (1 << 28), + GST_WFD_VESA_1920x1200P60 = (1 << 29) +} GstWFDVideoVESAResolution; + +typedef enum { + GST_WFD_HH_UNKNOWN = 0, + GST_WFD_HH_800x480P30 = (1 << 0), + GST_WFD_HH_800x480P60 = (1 << 1), + GST_WFD_HH_854x480P30 = (1 << 2), + GST_WFD_HH_854x480P60 = (1 << 3), + GST_WFD_HH_864x480P30 = (1 << 4), + GST_WFD_HH_864x480P60 = (1 << 5), + GST_WFD_HH_640x360P30 = (1 << 6), + GST_WFD_HH_640x360P60 = (1 << 7), + GST_WFD_HH_960x540P30 = (1 << 8), + GST_WFD_HH_960x540P60 = (1 << 9), + GST_WFD_HH_848x480P30 = (1 << 10), + GST_WFD_HH_848x480P60 = (1 << 11) +} GstWFDVideoHHResolution; + +typedef enum { + GST_WFD_H264_UNKNOWN_PROFILE= 0, + GST_WFD_H264_BASE_PROFILE = (1 << 0), + GST_WFD_H264_HIGH_PROFILE = (1 << 1) +} GstWFDVideoH264Profile; + +typedef enum { + GST_WFD_H264_LEVEL_UNKNOWN = 0, + GST_WFD_H264_LEVEL_3_1 = (1 << 0), + GST_WFD_H264_LEVEL_3_2 = (1 << 1), + GST_WFD_H264_LEVEL_4 = (1 << 2), + GST_WFD_H264_LEVEL_4_1 = (1 << 3), + GST_WFD_H264_LEVEL_4_2 = (1 << 4) +} GstWFDVideoH264Level; + +typedef enum { + GST_WFD_HDCP_NONE = 0, + GST_WFD_HDCP_2_0 = (1 << 0), + GST_WFD_HDCP_2_1 = (1 << 1) +} GstWFDHDCPProtection; + +typedef enum { + GST_WFD_SINK_UNKNOWN = -1, + GST_WFD_SINK_NOT_COUPLED = 0, + GST_WFD_SINK_COUPLED, + GST_WFD_SINK_TEARDOWN_COUPLING, + GST_WFD_SINK_RESERVED +} GstWFDCoupledSinkStatus; + +typedef enum { + GST_WFD_TRIGGER_UNKNOWN = 0, + GST_WFD_TRIGGER_SETUP, + GST_WFD_TRIGGER_PAUSE, + GST_WFD_TRIGGER_TEARDOWN, + GST_WFD_TRIGGER_PLAY +} GstWFDTrigger; + +typedef enum { + GST_WFD_RTSP_TRANS_UNKNOWN = 0, + GST_WFD_RTSP_TRANS_RTP = (1 << 0), + GST_WFD_RTSP_TRANS_RDT = (1 << 1) +} GstWFDRTSPTransMode; + +typedef enum { + GST_WFD_RTSP_PROFILE_UNKNOWN = 0, + GST_WFD_RTSP_PROFILE_AVP = (1 << 0), + GST_WFD_RTSP_PROFILE_SAVP = (1 << 1) +} GstWFDRTSPProfile; + +typedef enum { + GST_WFD_RTSP_LOWER_TRANS_UNKNOWN = 0, + GST_WFD_RTSP_LOWER_TRANS_UDP = (1 << 0), + GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST = (1 << 1), + GST_WFD_RTSP_LOWER_TRANS_TCP = (1 << 2), + GST_WFD_RTSP_LOWER_TRANS_HTTP = (1 << 3) +} GstWFDRTSPLowerTrans; + +typedef enum { + GST_WFD_PRIMARY_SINK = 0, + GST_WFD_SECONDARY_SINK +} GstWFDSinkType; + +typedef enum { + GST_WFD_CONNECTOR_VGA = 0, + GST_WFD_CONNECTOR_S, + GST_WFD_CONNECTOR_COMPOSITE, + GST_WFD_CONNECTOR_COMPONENT, + GST_WFD_CONNECTOR_DVI, + GST_WFD_CONNECTOR_HDMI, + GST_WFD_CONNECTOR_LVDS, + GST_WFD_CONNECTOR_RESERVED_7, + GST_WFD_CONNECTOR_JAPANESE_D, + GST_WFD_CONNECTOR_SDI, + GST_WFD_CONNECTOR_DP, + GST_WFD_CONNECTOR_RESERVED_11, + GST_WFD_CONNECTOR_UDI, + GST_WFD_CONNECTOR_NO = 254, + GST_WFD_CONNECTOR_PHYSICAL = 255 +} GstWFDConnector; + + +typedef struct { + gchar *audio_format; + guint32 modes; + guint latency; +} GstWFDAudioCodec; + +typedef struct { + guint count; + GstWFDAudioCodec *list; +} GstWFDAudioCodeclist; + + +typedef struct { + guint CEA_Support; + guint VESA_Support; + guint HH_Support; + guint latency; + guint min_slice_size; + guint slice_enc_params; + guint frame_rate_control_support; +} GstWFDVideoH264MiscParams; + +typedef struct { + guint profile; + guint level; + guint max_hres; + guint max_vres; + GstWFDVideoH264MiscParams misc_params; +} GstWFDVideoH264Codec; + +typedef struct { + guint native; + guint preferred_display_mode_supported; + GstWFDVideoH264Codec H264_codec; +} GstWFDVideoCodec; + +typedef struct { + guint count; + GstWFDVideoCodec *list; +} GstWFDVideoCodeclist; + +typedef struct { + guint video_3d_capability; + guint latency; + guint min_slice_size; + guint slice_enc_params; + guint frame_rate_control_support; +} GstWFD3DVideoH264MiscParams; + +typedef struct { + guint profile; + guint level; + GstWFD3DVideoH264MiscParams misc_params; + guint max_hres; + guint max_vres; +} GstWFD3DVideoH264Codec; + +typedef struct { + guint native; + guint preferred_display_mode_supported; + GstWFD3DVideoH264Codec H264_codec; +} GstWFD3dCapList; + +typedef struct { + guint count; + GstWFD3dCapList *list; +} GstWFD3DFormats; + +typedef struct { + gchar *hdcpversion; + gchar *TCPPort; +} GstWFDHdcp2Spec; + +typedef struct { + GstWFDHdcp2Spec *hdcp2_spec; +} GstWFDContentProtection; + +typedef struct { + guint edid_supported; + guint edid_block_count; + gchar *edid_payload; +} GstWFDDisplayEdid; + + +typedef struct { + guint status; + gchar *sink_address; +} GstWFDCoupled_sink_cap; + +typedef struct { + GstWFDCoupled_sink_cap *coupled_sink_cap; +} GstWFDCoupledSink; + +typedef struct { + gchar *wfd_trigger_method; +} GstWFDTriggerMethod; + +typedef struct { + gchar *wfd_url0; + gchar *wfd_url1; +} GstWFDPresentationUrl; + +typedef struct { + gchar *profile; + guint32 rtp_port0; + guint32 rtp_port1; + gchar *mode; +} GstWFDClientRtpPorts; + +typedef struct { + gchar *destination; +} GstWFDRoute; + +typedef struct { + gboolean I2CPresent; + guint32 I2C_port; +} GstWFDI2C; + +typedef struct { + guint64 PTS; + guint64 DTS; +} GstWFDAVFormatChangeTiming; + +typedef struct { + gboolean displaymodesupported; + guint64 p_clock; + guint32 H; + guint32 HB; + guint32 HSPOL_HSOFF; + guint32 HSW; + guint32 V; + guint32 VB; + guint32 VSPOL_VSOFF; + guint32 VSW; + guint VBS3D; + guint R; + guint V2d_s3d_modes; + guint P_depth; + GstWFDVideoH264Codec H264_codec; +} GstWFDPreferredDisplayMode; + +typedef struct { + gboolean standby_resume_cap; +} GstWFDStandbyResumeCapability; + +typedef struct { + gboolean wfd_standby; +} GstWFDStandby; + +typedef struct { + gboolean supported; + gint32 connector_type; +} GstWFDConnectorType; + +typedef struct { + gboolean idr_request; +} GstWFDIdrRequest; + +/** + * GstWFDMessage: + * @version: the protocol version + * @origin: owner/creator and session identifier + * @session_name: session name + * @information: session information + * @uri: URI of description + * @emails: array of #gchar with email addresses + * @phones: array of #gchar with phone numbers + * @connection: connection information for the session + * @bandwidths: array of #GstWFDBandwidth with bandwidth information + * @times: array of #GstWFDTime with time descriptions + * @zones: array of #GstWFDZone with time zone adjustments + * @key: encryption key + * @attributes: array of #GstWFDAttribute with session attributes + * @medias: array of #GstWFDMedia with media descriptions + * + * The contents of the WFD message. + */ +typedef struct { + GstWFDAudioCodeclist *audio_codecs; + GstWFDVideoCodeclist *video_formats; + GstWFD3DFormats *video_3d_formats; + GstWFDContentProtection *content_protection; + GstWFDDisplayEdid *display_edid; + GstWFDCoupledSink *coupled_sink; + GstWFDTriggerMethod *trigger_method; + GstWFDPresentationUrl *presentation_url; + GstWFDClientRtpPorts *client_rtp_ports; + GstWFDRoute *route; + GstWFDI2C *I2C; + GstWFDAVFormatChangeTiming *av_format_change_timing; + GstWFDPreferredDisplayMode *preferred_display_mode; + GstWFDStandbyResumeCapability *standby_resume_capability; + GstWFDStandby *standby; + GstWFDConnectorType *connector_type; + GstWFDIdrRequest *idr_request; +} GstWFDMessage; + +GType gst_wfd_message_get_type (void); + +#define GST_TYPE_WFD_MESSAGE (gst_wfd_message_get_type()) +#define GST_WFD_MESSAGE_CAST(object) ((GstWFDMessage *)(object)) +#define GST_WFD_MESSAGE(object) (GST_WFD_MESSAGE_CAST(object)) + +/* Session descriptions */ +GstWFDResult gst_wfd_message_new (GstWFDMessage **msg); +GstWFDResult gst_wfd_message_init (GstWFDMessage *msg); +GstWFDResult gst_wfd_message_uninit (GstWFDMessage *msg); +GstWFDResult gst_wfd_message_free (GstWFDMessage *msg); +GstWFDResult gst_wfd_message_copy (const GstWFDMessage *msg, GstWFDMessage **copy); + +GstWFDResult gst_wfd_message_parse_buffer (const guint8 *data, guint size, GstWFDMessage *msg); +gchar* gst_wfd_message_as_text (const GstWFDMessage *msg); +gchar* gst_wfd_message_param_names_as_text (const GstWFDMessage *msg); +GstWFDResult gst_wfd_message_dump (const GstWFDMessage *msg); + + +GstWFDResult gst_wfd_message_set_supported_audio_format(GstWFDMessage *msg, + GstWFDAudioFormats a_codec, + guint a_freq, guint a_channels, + guint a_bitwidth, guint32 a_latency); + +GstWFDResult gst_wfd_message_set_prefered_audio_format(GstWFDMessage *msg, + GstWFDAudioFormats a_codec, + GstWFDAudioFreq a_freq, + GstWFDAudioChannels a_channels, + guint a_bitwidth, guint32 a_latency); + +GstWFDResult gst_wfd_message_get_supported_audio_format (GstWFDMessage *msg, + guint *a_codec, + guint *a_freq, + guint *a_channels, + guint *a_bitwidth, + guint32 *a_latency); + +GstWFDResult gst_wfd_message_get_prefered_audio_format (GstWFDMessage *msg, + GstWFDAudioFormats *a_codec, + GstWFDAudioFreq *a_freq, + GstWFDAudioChannels *a_channels, + guint *a_bitwidth, guint32 *a_latency); + +GstWFDResult gst_wfd_message_set_supported_video_format (GstWFDMessage *msg, + GstWFDVideoCodecs v_codec, + GstWFDVideoNativeResolution v_native, + guint64 v_native_resolution, + guint64 v_cea_resolution, + guint64 v_vesa_resolution, + guint64 v_hh_resolution, + guint v_profile, + guint v_level, + guint32 v_latency, + guint32 v_max_height, + guint32 v_max_width, + guint32 min_slice_size, + guint32 slice_enc_params, + guint frame_rate_control); + +GstWFDResult gst_wfd_message_set_prefered_video_format(GstWFDMessage *msg, + GstWFDVideoCodecs v_codec, + GstWFDVideoNativeResolution v_native, + guint64 v_native_resolution, + GstWFDVideoCEAResolution v_cea_resolution, + GstWFDVideoVESAResolution v_vesa_resolution, + GstWFDVideoHHResolution v_hh_resolution, + GstWFDVideoH264Profile v_profile, + GstWFDVideoH264Level v_level, + guint32 v_latency, + guint32 v_max_height, + guint32 v_max_width, + guint32 min_slice_size, + guint32 slice_enc_params, + guint frame_rate_control); + +GstWFDResult gst_wfd_message_get_supported_video_format(GstWFDMessage *msg, + GstWFDVideoCodecs *v_codec, + GstWFDVideoNativeResolution *v_native, + guint64 *v_native_resolution, + guint64 *v_cea_resolution, + guint64 *v_vesa_resolution, + guint64 *v_hh_resolution, + guint *v_profile, + guint *v_level, + guint32 *v_latency, + guint32 *v_max_height, + guint32 *v_max_width, + guint32 *min_slice_size, + guint32 *slice_enc_params, + guint *frame_rate_control); + +GstWFDResult gst_wfd_message_get_prefered_video_format(GstWFDMessage *msg, + GstWFDVideoCodecs *v_codec, + GstWFDVideoNativeResolution *v_native, + guint64 *v_native_resolution, + GstWFDVideoCEAResolution *v_cea_resolution, + GstWFDVideoVESAResolution *v_vesa_resolution, + GstWFDVideoHHResolution *v_hh_resolution, + GstWFDVideoH264Profile *v_profile, + GstWFDVideoH264Level *v_level, + guint32 *v_latency, + guint32 *v_max_height, + guint32 *v_max_width, + guint32 *min_slice_size, + guint32 *slice_enc_params, + guint *frame_rate_control); + +GstWFDResult gst_wfd_message_set_display_edid (GstWFDMessage *msg, + gboolean edid_supported, + guint32 edid_blockcount, + gchar *edid_playload); + +GstWFDResult gst_wfd_message_get_display_edid (GstWFDMessage *msg, + gboolean *edid_supported, + guint32 *edid_blockcount, + gchar **edid_playload); + +GstWFDResult gst_wfd_message_set_contentprotection_type (GstWFDMessage *msg, + GstWFDHDCPProtection hdcpversion, + guint32 TCPPort); + +GstWFDResult gst_wfd_message_get_contentprotection_type (GstWFDMessage *msg, + GstWFDHDCPProtection *hdcpversion, + guint32 *TCPPort); + +GstWFDResult gst_wfd_messge_set_prefered_rtp_ports (GstWFDMessage *msg, + GstWFDRTSPTransMode trans, + GstWFDRTSPProfile profile, + GstWFDRTSPLowerTrans lowertrans, + guint32 rtp_port0, + guint32 rtp_port1); + +GstWFDResult gst_wfd_message_get_prefered_rtp_ports (GstWFDMessage *msg, + GstWFDRTSPTransMode *trans, + GstWFDRTSPProfile *profile, + GstWFDRTSPLowerTrans *lowertrans, + guint32 *rtp_port0, + guint32 *rtp_port1); + +GstWFDResult gst_wfd_message_set_presentation_url(GstWFDMessage *msg, + gchar *wfd_url0, gchar *wfd_url1); + +GstWFDResult gst_wfd_message_get_presentation_url(GstWFDMessage *msg, gchar **wfd_url0, + gchar **wfd_url1); + +GstWFDResult gst_wfd_message_set_av_format_change_timing(GstWFDMessage *msg, + guint64 PTS, + guint64 DTS); + +GstWFDResult gst_wfd_message_get_av_format_change_timing(GstWFDMessage *msg, + guint64 *PTS, + guint64 *DTS); +G_END_DECLS + +#endif /* __GST_WFD_MESSAGE_H__ */ diff --git a/gst/rtsp-server/rtsp-address-pool.c b/gst/rtsp-server/rtsp-address-pool.c new file mode 100644 index 0000000..1343839 --- /dev/null +++ b/gst/rtsp-server/rtsp-address-pool.c @@ -0,0 +1,751 @@ +/* GStreamer + * Copyright (C) 2012 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-address-pool + * @short_description: A pool of network addresses + * @see_also: #GstRTSPStream, #GstRTSPStreamTransport + * + * The #GstRTSPAddressPool is an object that maintains a collection of network + * addresses. It is used to allocate server ports and server multicast addresses + * but also to reserve client provided destination addresses. + * + * A range of addresses can be added with gst_rtsp_address_pool_add_range(). + * Both multicast and unicast addresses can be added. + * + * With gst_rtsp_address_pool_acquire_address() an unused address and port range + * can be acquired from the pool. With gst_rtsp_address_pool_reserve_address() a + * specific address can be retrieved. Both methods return a boxed + * #GstRTSPAddress that should be freed with gst_rtsp_address_free() after + * usage, which brings the address back into the pool. + * + * Last reviewed on 2013-07-16 (1.0.0) + */ + +#include +#include + +#include "rtsp-address-pool.h" + +/** + * gst_rtsp_address_copy: + * @addr: a #GstRTSPAddress + * + * Make a copy of @addr. + * + * Returns: a copy of @addr. + */ +GstRTSPAddress * +gst_rtsp_address_copy (GstRTSPAddress * addr) +{ + GstRTSPAddress *copy; + + g_return_val_if_fail (addr != NULL, NULL); + + copy = g_slice_dup (GstRTSPAddress, addr); + /* only release to the pool when the original is freed. It's a bit + * weird but this will do for now as it avoid us to use refcounting. */ + copy->pool = NULL; + copy->address = g_strdup (copy->address); + + return copy; +} + +static void gst_rtsp_address_pool_release_address (GstRTSPAddressPool * pool, + GstRTSPAddress * addr); + +/** + * gst_rtsp_address_free: + * @addr: a #GstRTSPAddress + * + * Free @addr and releasing it back into the pool when owned by a + * pool. + */ +void +gst_rtsp_address_free (GstRTSPAddress * addr) +{ + g_return_if_fail (addr != NULL); + + if (addr->pool) { + /* unrefs the pool and sets it to NULL */ + gst_rtsp_address_pool_release_address (addr->pool, addr); + } + g_free (addr->address); + g_slice_free (GstRTSPAddress, addr); +} + +G_DEFINE_BOXED_TYPE (GstRTSPAddress, gst_rtsp_address, + (GBoxedCopyFunc) gst_rtsp_address_copy, + (GBoxedFreeFunc) gst_rtsp_address_free); + +GST_DEBUG_CATEGORY_STATIC (rtsp_address_pool_debug); +#define GST_CAT_DEFAULT rtsp_address_pool_debug + +#define GST_RTSP_ADDRESS_POOL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_ADDRESS_POOL, GstRTSPAddressPoolPrivate)) + +struct _GstRTSPAddressPoolPrivate +{ + GMutex lock; /* protects everything in this struct */ + GList *addresses; + GList *allocated; + + gboolean has_unicast_addresses; +}; + +#define ADDR_IS_IPV4(a) ((a)->size == 4) +#define ADDR_IS_IPV6(a) ((a)->size == 16) +#define ADDR_IS_EVEN_PORT(a) (((a)->port & 1) == 0) + +typedef struct +{ + guint8 bytes[16]; + gsize size; + guint16 port; +} Addr; + +typedef struct +{ + Addr min; + Addr max; + guint8 ttl; +} AddrRange; + +#define RANGE_IS_SINGLE(r) (memcmp ((r)->min.bytes, (r)->max.bytes, (r)->min.size) == 0) + +#define gst_rtsp_address_pool_parent_class parent_class +G_DEFINE_TYPE (GstRTSPAddressPool, gst_rtsp_address_pool, G_TYPE_OBJECT); + +static void gst_rtsp_address_pool_finalize (GObject * obj); + +static void +gst_rtsp_address_pool_class_init (GstRTSPAddressPoolClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = gst_rtsp_address_pool_finalize; + + g_type_class_add_private (klass, sizeof (GstRTSPAddressPoolPrivate)); + + GST_DEBUG_CATEGORY_INIT (rtsp_address_pool_debug, "rtspaddresspool", 0, + "GstRTSPAddressPool"); +} + +static void +gst_rtsp_address_pool_init (GstRTSPAddressPool * pool) +{ + pool->priv = GST_RTSP_ADDRESS_POOL_GET_PRIVATE (pool); + + g_mutex_init (&pool->priv->lock); +} + +static void +free_range (AddrRange * range) +{ + g_slice_free (AddrRange, range); +} + +static void +gst_rtsp_address_pool_finalize (GObject * obj) +{ + GstRTSPAddressPool *pool; + + pool = GST_RTSP_ADDRESS_POOL (obj); + + g_list_free_full (pool->priv->addresses, (GDestroyNotify) free_range); + g_list_free_full (pool->priv->allocated, (GDestroyNotify) free_range); + g_mutex_clear (&pool->priv->lock); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +/** + * gst_rtsp_address_pool_new: + * + * Make a new #GstRTSPAddressPool. + * + * Returns: (transfer full): a new #GstRTSPAddressPool + */ +GstRTSPAddressPool * +gst_rtsp_address_pool_new (void) +{ + GstRTSPAddressPool *pool; + + pool = g_object_new (GST_TYPE_RTSP_ADDRESS_POOL, NULL); + + return pool; +} + +/** + * gst_rtsp_address_pool_clear: + * @pool: a #GstRTSPAddressPool + * + * Clear all addresses in @pool. There should be no outstanding + * allocations. + */ +void +gst_rtsp_address_pool_clear (GstRTSPAddressPool * pool) +{ + GstRTSPAddressPoolPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool)); + g_return_if_fail (pool->priv->allocated == NULL); + + priv = pool->priv; + + g_mutex_lock (&priv->lock); + g_list_free_full (priv->addresses, (GDestroyNotify) free_range); + priv->addresses = NULL; + g_mutex_unlock (&priv->lock); +} + +static gboolean +fill_address (const gchar * address, guint16 port, Addr * addr, + gboolean is_multicast) +{ + GInetAddress *inet; + + inet = g_inet_address_new_from_string (address); + if (inet == NULL) + return FALSE; + + if (is_multicast != g_inet_address_get_is_multicast (inet)) { + g_object_unref (inet); + return FALSE; + } + + addr->size = g_inet_address_get_native_size (inet); + memcpy (addr->bytes, g_inet_address_to_bytes (inet), addr->size); + g_object_unref (inet); + addr->port = port; + + return TRUE; +} + +static gchar * +get_address_string (Addr * addr) +{ + gchar *res; + GInetAddress *inet; + + inet = g_inet_address_new_from_bytes (addr->bytes, + addr->size == 4 ? G_SOCKET_FAMILY_IPV4 : G_SOCKET_FAMILY_IPV6); + res = g_inet_address_to_string (inet); + g_object_unref (inet); + + return res; +} + +/** + * gst_rtsp_address_pool_add_range: + * @pool: a #GstRTSPAddressPool + * @min_address: a minimum address to add + * @max_address: a maximum address to add + * @min_port: the minimum port + * @max_port: the maximum port + * @ttl: a TTL or 0 for unicast addresses + * + * Adds the addresses from @min_addess to @max_address (inclusive) + * to @pool. The valid port range for the addresses will be from @min_port to + * @max_port inclusive. + * + * When @ttl is 0, @min_address and @max_address should be unicast addresses. + * @min_address and @max_address can be set to + * #GST_RTSP_ADDRESS_POOL_ANY_IPV4 or #GST_RTSP_ADDRESS_POOL_ANY_IPV6 to bind + * to all available IPv4 or IPv6 addresses. + * + * When @ttl > 0, @min_address and @max_address should be multicast addresses. + * + * Returns: %TRUE if the addresses could be added. + */ +gboolean +gst_rtsp_address_pool_add_range (GstRTSPAddressPool * pool, + const gchar * min_address, const gchar * max_address, + guint16 min_port, guint16 max_port, guint8 ttl) +{ + AddrRange *range; + GstRTSPAddressPoolPrivate *priv; + gboolean is_multicast; + + g_return_val_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool), FALSE); + g_return_val_if_fail (min_port <= max_port, FALSE); + + priv = pool->priv; + + is_multicast = ttl != 0; + + range = g_slice_new0 (AddrRange); + + if (!fill_address (min_address, min_port, &range->min, is_multicast)) + goto invalid; + if (!fill_address (max_address, max_port, &range->max, is_multicast)) + goto invalid; + + if (range->min.size != range->max.size) + goto invalid; + if (memcmp (range->min.bytes, range->max.bytes, range->min.size) > 0) + goto invalid; + + range->ttl = ttl; + + GST_DEBUG_OBJECT (pool, "adding %s-%s:%u-%u ttl %u", min_address, max_address, + min_port, max_port, ttl); + + g_mutex_lock (&priv->lock); + priv->addresses = g_list_prepend (priv->addresses, range); + + if (!is_multicast) + priv->has_unicast_addresses = TRUE; + g_mutex_unlock (&priv->lock); + + return TRUE; + + /* ERRORS */ +invalid: + { + GST_ERROR_OBJECT (pool, "invalid address range %s-%s", min_address, + max_address); + g_slice_free (AddrRange, range); + return FALSE; + } +} + +static void +inc_address (Addr * addr, guint count) +{ + gint i; + guint carry; + + carry = count; + for (i = addr->size - 1; i >= 0 && carry > 0; i--) { + carry += addr->bytes[i]; + addr->bytes[i] = carry & 0xff; + carry >>= 8; + } +} + +/* tells us the number of addresses between min_addr and max_addr */ +static guint +diff_address (Addr * max_addr, Addr * min_addr) +{ + gint i; + guint result = 0; + + g_return_val_if_fail (min_addr->size == max_addr->size, 0); + + for (i = 0; i < min_addr->size; i++) { + g_return_val_if_fail (result < (1 << 24), result); + + result <<= 8; + result += max_addr->bytes[i] - min_addr->bytes[i]; + } + + return result; +} + +static AddrRange * +split_range (GstRTSPAddressPool * pool, AddrRange * range, guint skip_addr, + guint skip_port, gint n_ports) +{ + GstRTSPAddressPoolPrivate *priv = pool->priv; + AddrRange *temp; + + if (skip_addr) { + temp = g_slice_dup (AddrRange, range); + memcpy (temp->max.bytes, temp->min.bytes, temp->min.size); + inc_address (&temp->max, skip_addr - 1); + priv->addresses = g_list_prepend (priv->addresses, temp); + + inc_address (&range->min, skip_addr); + } + + if (!RANGE_IS_SINGLE (range)) { + /* min and max are not the same, we have more than one address. */ + temp = g_slice_dup (AddrRange, range); + /* increment the range min address */ + inc_address (&temp->min, 1); + /* and store back in pool */ + priv->addresses = g_list_prepend (priv->addresses, temp); + + /* adjust range with only the first address */ + memcpy (range->max.bytes, range->min.bytes, range->min.size); + } + + /* range now contains only one single address */ + if (skip_port > 0) { + /* make a range with the skipped ports */ + temp = g_slice_dup (AddrRange, range); + temp->max.port = temp->min.port + skip_port - 1; + /* and store back in pool */ + priv->addresses = g_list_prepend (priv->addresses, temp); + + /* increment range port */ + range->min.port += skip_port; + } + /* range now contains single address with desired port number */ + if (range->max.port - range->min.port + 1 > n_ports) { + /* make a range with the remaining ports */ + temp = g_slice_dup (AddrRange, range); + temp->min.port += n_ports; + /* and store back in pool */ + priv->addresses = g_list_prepend (priv->addresses, temp); + + /* and truncate port */ + range->max.port = range->min.port + n_ports - 1; + } + return range; +} + +/** + * gst_rtsp_address_pool_acquire_address: + * @pool: a #GstRTSPAddressPool + * @flags: flags + * @n_ports: the amount of ports + * + * Take an address and ports from @pool. @flags can be used to control the + * allocation. @n_ports consecutive ports will be allocated of which the first + * one can be found in @port. + * + * Returns: (nullable): a #GstRTSPAddress that should be freed with + * gst_rtsp_address_free after use or %NULL when no address could be + * acquired. + */ +GstRTSPAddress * +gst_rtsp_address_pool_acquire_address (GstRTSPAddressPool * pool, + GstRTSPAddressFlags flags, gint n_ports) +{ + GstRTSPAddressPoolPrivate *priv; + GList *walk, *next; + AddrRange *result; + GstRTSPAddress *addr; + + g_return_val_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool), NULL); + g_return_val_if_fail (n_ports > 0, NULL); + + priv = pool->priv; + result = NULL; + addr = NULL; + + g_mutex_lock (&priv->lock); + /* go over available ranges */ + for (walk = priv->addresses; walk; walk = next) { + AddrRange *range; + gint ports, skip; + + range = walk->data; + next = walk->next; + + /* check address type when given */ + if (flags & GST_RTSP_ADDRESS_FLAG_IPV4 && !ADDR_IS_IPV4 (&range->min)) + continue; + if (flags & GST_RTSP_ADDRESS_FLAG_IPV6 && !ADDR_IS_IPV6 (&range->min)) + continue; + if (flags & GST_RTSP_ADDRESS_FLAG_MULTICAST && range->ttl == 0) + continue; + if (flags & GST_RTSP_ADDRESS_FLAG_UNICAST && range->ttl != 0) + continue; + + /* check for enough ports */ + ports = range->max.port - range->min.port + 1; + if (flags & GST_RTSP_ADDRESS_FLAG_EVEN_PORT + && !ADDR_IS_EVEN_PORT (&range->min)) + skip = 1; + else + skip = 0; + if (ports - skip < n_ports) + continue; + + /* we found a range, remove from the list */ + priv->addresses = g_list_delete_link (priv->addresses, walk); + /* now split and exit our loop */ + result = split_range (pool, range, 0, skip, n_ports); + priv->allocated = g_list_prepend (priv->allocated, result); + break; + } + g_mutex_unlock (&priv->lock); + + if (result) { + addr = g_slice_new0 (GstRTSPAddress); + addr->pool = g_object_ref (pool); + addr->address = get_address_string (&result->min); + addr->n_ports = n_ports; + addr->port = result->min.port; + addr->ttl = result->ttl; + addr->priv = result; + + GST_DEBUG_OBJECT (pool, "got address %s:%u ttl %u", addr->address, + addr->port, addr->ttl); + } + + return addr; +} + +/** + * gst_rtsp_address_pool_release_address: + * @pool: a #GstRTSPAddressPool + * @id: an address id + * + * Release a previously acquired address (with + * gst_rtsp_address_pool_acquire_address()) back into @pool. + */ +static void +gst_rtsp_address_pool_release_address (GstRTSPAddressPool * pool, + GstRTSPAddress * addr) +{ + GstRTSPAddressPoolPrivate *priv; + GList *find; + AddrRange *range; + + g_return_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool)); + g_return_if_fail (addr != NULL); + g_return_if_fail (addr->pool == pool); + + priv = pool->priv; + range = addr->priv; + + /* we don't want to free twice */ + addr->priv = NULL; + addr->pool = NULL; + + g_mutex_lock (&priv->lock); + find = g_list_find (priv->allocated, range); + if (find == NULL) + goto not_found; + + priv->allocated = g_list_delete_link (priv->allocated, find); + + /* FIXME, merge and do something clever */ + priv->addresses = g_list_prepend (priv->addresses, range); + g_mutex_unlock (&priv->lock); + + g_object_unref (pool); + + return; + + /* ERRORS */ +not_found: + { + g_warning ("Released unknown address %p", addr); + g_mutex_unlock (&priv->lock); + return; + } +} + +static void +dump_range (AddrRange * range, GstRTSPAddressPool * pool) +{ + gchar *addr1, *addr2; + + addr1 = get_address_string (&range->min); + addr2 = get_address_string (&range->max); + g_print (" address %s-%s, port %u-%u, ttl %u\n", addr1, addr2, + range->min.port, range->max.port, range->ttl); + g_free (addr1); + g_free (addr2); +} + +/** + * gst_rtsp_address_pool_dump: + * @pool: a #GstRTSPAddressPool + * + * Dump the free and allocated addresses to stdout. + */ +void +gst_rtsp_address_pool_dump (GstRTSPAddressPool * pool) +{ + GstRTSPAddressPoolPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool)); + + priv = pool->priv; + + g_mutex_lock (&priv->lock); + g_print ("free:\n"); + g_list_foreach (priv->addresses, (GFunc) dump_range, pool); + g_print ("allocated:\n"); + g_list_foreach (priv->allocated, (GFunc) dump_range, pool); + g_mutex_unlock (&priv->lock); +} + +static GList * +find_address_in_ranges (GList * addresses, Addr * addr, guint port, + guint n_ports, guint ttl) +{ + GList *walk, *next; + + /* go over available ranges */ + for (walk = addresses; walk; walk = next) { + AddrRange *range; + + range = walk->data; + next = walk->next; + + /* Not the right type of address */ + if (range->min.size != addr->size) + continue; + + /* Check that the address is in the interval */ + if (memcmp (range->min.bytes, addr->bytes, addr->size) > 0 || + memcmp (range->max.bytes, addr->bytes, addr->size) < 0) + continue; + + /* Make sure the requested ports are inside the range */ + if (port < range->min.port || port + n_ports - 1 > range->max.port) + continue; + + if (ttl != range->ttl) + continue; + + break; + } + + return walk; +} + +/** + * gst_rtsp_address_pool_reserve_address: + * @pool: a #GstRTSPAddressPool + * @ip_address: The IP address to reserve + * @port: The first port to reserve + * @n_ports: The number of ports + * @ttl: The requested ttl + * @address: (out): storage for a #GstRTSPAddress + * + * Take a specific address and ports from @pool. @n_ports consecutive + * ports will be allocated of which the first one can be found in + * @port. + * + * If @ttl is 0, @address should be a unicast address. If @ttl > 0, @address + * should be a valid multicast address. + * + * Returns: #GST_RTSP_ADDRESS_POOL_OK if an address was reserved. The address + * is returned in @address and should be freed with gst_rtsp_address_free + * after use. + */ +GstRTSPAddressPoolResult +gst_rtsp_address_pool_reserve_address (GstRTSPAddressPool * pool, + const gchar * ip_address, guint port, guint n_ports, guint ttl, + GstRTSPAddress ** address) +{ + GstRTSPAddressPoolPrivate *priv; + Addr input_addr; + GList *list; + AddrRange *addr_range; + GstRTSPAddress *addr; + gboolean is_multicast; + GstRTSPAddressPoolResult result; + + g_return_val_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool), + GST_RTSP_ADDRESS_POOL_EINVAL); + g_return_val_if_fail (ip_address != NULL, GST_RTSP_ADDRESS_POOL_EINVAL); + g_return_val_if_fail (port > 0, GST_RTSP_ADDRESS_POOL_EINVAL); + g_return_val_if_fail (n_ports > 0, GST_RTSP_ADDRESS_POOL_EINVAL); + g_return_val_if_fail (address != NULL, GST_RTSP_ADDRESS_POOL_EINVAL); + + priv = pool->priv; + addr_range = NULL; + addr = NULL; + is_multicast = ttl != 0; + + if (!fill_address (ip_address, port, &input_addr, is_multicast)) + goto invalid; + + g_mutex_lock (&priv->lock); + list = find_address_in_ranges (priv->addresses, &input_addr, port, n_ports, + ttl); + if (list != NULL) { + AddrRange *range = list->data; + guint skip_port, skip_addr; + + skip_addr = diff_address (&input_addr, &range->min); + skip_port = port - range->min.port; + + GST_DEBUG_OBJECT (pool, "diff 0x%08x/%u", skip_addr, skip_port); + + /* we found a range, remove from the list */ + priv->addresses = g_list_delete_link (priv->addresses, list); + /* now split and exit our loop */ + addr_range = split_range (pool, range, skip_addr, skip_port, n_ports); + priv->allocated = g_list_prepend (priv->allocated, addr_range); + } + + if (addr_range) { + addr = g_slice_new0 (GstRTSPAddress); + addr->pool = g_object_ref (pool); + addr->address = get_address_string (&addr_range->min); + addr->n_ports = n_ports; + addr->port = addr_range->min.port; + addr->ttl = addr_range->ttl; + addr->priv = addr_range; + + result = GST_RTSP_ADDRESS_POOL_OK; + GST_DEBUG_OBJECT (pool, "reserved address %s:%u ttl %u", addr->address, + addr->port, addr->ttl); + } else { + /* We failed to reserve the address. Check if it was because the address + * was already in use or if it wasn't in the pool to begin with */ + list = find_address_in_ranges (priv->allocated, &input_addr, port, n_ports, + ttl); + if (list != NULL) { + result = GST_RTSP_ADDRESS_POOL_ERESERVED; + } else { + result = GST_RTSP_ADDRESS_POOL_ERANGE; + } + } + g_mutex_unlock (&priv->lock); + + *address = addr; + return result; + + /* ERRORS */ +invalid: + { + GST_ERROR_OBJECT (pool, "invalid address %s:%u/%u/%u", ip_address, + port, n_ports, ttl); + *address = NULL; + return GST_RTSP_ADDRESS_POOL_EINVAL; + } +} + +/** + * gst_rtsp_address_pool_has_unicast_addresses: + * @pool: a #GstRTSPAddressPool + * + * Used to know if the pool includes any unicast addresses. + * + * Returns: %TRUE if the pool includes any unicast addresses, %FALSE otherwise + */ + +gboolean +gst_rtsp_address_pool_has_unicast_addresses (GstRTSPAddressPool * pool) +{ + GstRTSPAddressPoolPrivate *priv; + gboolean has_unicast_addresses; + + g_return_val_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool), FALSE); + + priv = pool->priv; + + g_mutex_lock (&priv->lock); + has_unicast_addresses = priv->has_unicast_addresses; + g_mutex_unlock (&priv->lock); + + return has_unicast_addresses; +} diff --git a/gst/rtsp-server/rtsp-address-pool.h b/gst/rtsp-server/rtsp-address-pool.h new file mode 100644 index 0000000..a473bdf --- /dev/null +++ b/gst/rtsp-server/rtsp-address-pool.h @@ -0,0 +1,182 @@ +/* GStreamer + * Copyright (C) 2012 Wim Taymans + * + * 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. + */ + +#include + +#ifndef __GST_RTSP_ADDRESS_POOL_H__ +#define __GST_RTSP_ADDRESS_POOL_H__ + +G_BEGIN_DECLS + +#define GST_TYPE_RTSP_ADDRESS_POOL (gst_rtsp_address_pool_get_type ()) +#define GST_IS_RTSP_ADDRESS_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_ADDRESS_POOL)) +#define GST_IS_RTSP_ADDRESS_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_ADDRESS_POOL)) +#define GST_RTSP_ADDRESS_POOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_ADDRESS_POOL, GstRTSPAddressPoolClass)) +#define GST_RTSP_ADDRESS_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_ADDRESS_POOL, GstRTSPAddressPool)) +#define GST_RTSP_ADDRESS_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_ADDRESS_POOL, GstRTSPAddressPoolClass)) +#define GST_RTSP_ADDRESS_POOL_CAST(obj) ((GstRTSPAddressPool*)(obj)) +#define GST_RTSP_ADDRESS_POOL_CLASS_CAST(klass) ((GstRTSPAddressPoolClass*)(klass)) + +/** + * GstRTSPAddressPoolResult: + * @GST_RTSP_ADDRESS_POOL_OK: no error + * @GST_RTSP_ADDRESS_POOL_EINVAL:invalid arguments were provided to a function + * @GST_RTSP_ADDRESS_POOL_ERESERVED: the addres has already been reserved + * @GST_RTSP_ADDRESS_POOL_ERANGE: the address is not in the pool + * @GST_RTSP_ADDRESS_POOL_ELAST: last error + * + * Result codes from RTSP address pool functions. + */ +typedef enum { + GST_RTSP_ADDRESS_POOL_OK = 0, + /* errors */ + GST_RTSP_ADDRESS_POOL_EINVAL = -1, + GST_RTSP_ADDRESS_POOL_ERESERVED = -2, + GST_RTSP_ADDRESS_POOL_ERANGE = -3, + + GST_RTSP_ADDRESS_POOL_ELAST = -4, +} GstRTSPAddressPoolResult; + + +typedef struct _GstRTSPAddress GstRTSPAddress; + +typedef struct _GstRTSPAddressPool GstRTSPAddressPool; +typedef struct _GstRTSPAddressPoolClass GstRTSPAddressPoolClass; +typedef struct _GstRTSPAddressPoolPrivate GstRTSPAddressPoolPrivate; + +/** + * GstRTSPAddress: + * @pool: the #GstRTSPAddressPool owner of this address + * @address: the address + * @port: the port number + * @n_ports: number of ports + * @ttl: TTL or 0 for unicast addresses + * + * An address + */ +struct _GstRTSPAddress { + GstRTSPAddressPool *pool; + + gchar *address; + guint16 port; + gint n_ports; + guint8 ttl; + + /**/ + gpointer priv; +}; + +GType gst_rtsp_address_get_type (void); + +GstRTSPAddress * gst_rtsp_address_copy (GstRTSPAddress *addr); +void gst_rtsp_address_free (GstRTSPAddress *addr); + +/** + * GstRTSPAddressFlags: + * @GST_RTSP_ADDRESS_FLAG_NONE: no flags + * @GST_RTSP_ADDRESS_FLAG_IPV4: an IPv4 address + * @GST_RTSP_ADDRESS_FLAG_IPV6: and IPv6 address + * @GST_RTSP_ADDRESS_FLAG_EVEN_PORT: address with an even port + * @GST_RTSP_ADDRESS_FLAG_MULTICAST: a multicast address + * @GST_RTSP_ADDRESS_FLAG_UNICAST: a unicast address + * + * Flags used to control allocation of addresses + */ +typedef enum { + GST_RTSP_ADDRESS_FLAG_NONE = 0, + GST_RTSP_ADDRESS_FLAG_IPV4 = (1 << 0), + GST_RTSP_ADDRESS_FLAG_IPV6 = (1 << 1), + GST_RTSP_ADDRESS_FLAG_EVEN_PORT = (1 << 2), + GST_RTSP_ADDRESS_FLAG_MULTICAST = (1 << 3), + GST_RTSP_ADDRESS_FLAG_UNICAST = (1 << 4), +} GstRTSPAddressFlags; + +/** + * GST_RTSP_ADDRESS_POOL_ANY_IPV4: + * + * Used with gst_rtsp_address_pool_add_range() to bind to all + * IPv4 addresses + */ +#define GST_RTSP_ADDRESS_POOL_ANY_IPV4 "0.0.0.0" + +/** + * GST_RTSP_ADDRESS_POOL_ANY_IPV6: + * + * Used with gst_rtsp_address_pool_add_range() to bind to all + * IPv6 addresses + */ +#define GST_RTSP_ADDRESS_POOL_ANY_IPV6 "::" + +/** + * GstRTSPAddressPool: + * @parent: the parent GObject + * + * An address pool, all member are private + */ +struct _GstRTSPAddressPool { + GObject parent; + + /*< private >*/ + GstRTSPAddressPoolPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPAddressPoolClass: + * + * Opaque Address pool class. + */ +struct _GstRTSPAddressPoolClass { + GObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_rtsp_address_pool_get_type (void); + +/* create a new address pool */ +GstRTSPAddressPool * gst_rtsp_address_pool_new (void); + +void gst_rtsp_address_pool_clear (GstRTSPAddressPool * pool); +void gst_rtsp_address_pool_dump (GstRTSPAddressPool * pool); + +gboolean gst_rtsp_address_pool_add_range (GstRTSPAddressPool * pool, + const gchar *min_address, + const gchar *max_address, + guint16 min_port, + guint16 max_port, + guint8 ttl); + +GstRTSPAddress * gst_rtsp_address_pool_acquire_address (GstRTSPAddressPool * pool, + GstRTSPAddressFlags flags, + gint n_ports); + +GstRTSPAddressPoolResult gst_rtsp_address_pool_reserve_address (GstRTSPAddressPool * pool, + const gchar *ip_address, + guint port, + guint n_ports, + guint ttl, + GstRTSPAddress ** address); + +gboolean gst_rtsp_address_pool_has_unicast_addresses (GstRTSPAddressPool * pool); + +G_END_DECLS + +#endif /* __GST_RTSP_ADDRESS_POOL_H__ */ diff --git a/gst/rtsp-server/rtsp-auth.c b/gst/rtsp-server/rtsp-auth.c new file mode 100644 index 0000000..b0e924e --- /dev/null +++ b/gst/rtsp-server/rtsp-auth.c @@ -0,0 +1,636 @@ +/* GStreamer + * Copyright (C) 2010 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-auth + * @short_description: Authentication and authorization + * @see_also: #GstRTSPPermissions, #GstRTSPToken + * + * The #GstRTSPAuth object is responsible for checking if the current user is + * allowed to perform requested actions. The default implementation has some + * reasonable checks but subclasses can implement custom security policies. + * + * A new auth object is made with gst_rtsp_auth_new(). It is usually configured + * on the #GstRTSPServer object. + * + * The RTSP server will call gst_rtsp_auth_check() with a string describing the + * check to perform. The possible checks are prefixed with + * GST_RTSP_AUTH_CHECK_*. Depending on the check, the default implementation + * will use the current #GstRTSPToken, #GstRTSPContext and + * #GstRTSPPermissions on the object to check if an operation is allowed. + * + * The default #GstRTSPAuth object has support for basic authentication. With + * gst_rtsp_auth_add_basic() you can add a basic authentication string together + * with the #GstRTSPToken that will become active when successfully + * authenticated. + * + * When a TLS certificate has been set with gst_rtsp_auth_set_tls_certificate(), + * the default auth object will require the client to connect with a TLS + * connection. + * + * Last reviewed on 2013-07-16 (1.0.0) + */ + +#include + +#include "rtsp-auth.h" + +#define GST_RTSP_AUTH_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_AUTH, GstRTSPAuthPrivate)) + +struct _GstRTSPAuthPrivate +{ + GMutex lock; + + /* the TLS certificate */ + GTlsCertificate *certificate; + GHashTable *basic; /* protected by lock */ + GstRTSPToken *default_token; + GstRTSPMethod methods; +}; + +enum +{ + PROP_0, + PROP_LAST +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_auth_debug); +#define GST_CAT_DEFAULT rtsp_auth_debug + +static void gst_rtsp_auth_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_auth_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); +static void gst_rtsp_auth_finalize (GObject * obj); + +static gboolean default_authenticate (GstRTSPAuth * auth, GstRTSPContext * ctx); +static gboolean default_check (GstRTSPAuth * auth, GstRTSPContext * ctx, + const gchar * check); + +G_DEFINE_TYPE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT); + +static void +gst_rtsp_auth_class_init (GstRTSPAuthClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPAuthPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gst_rtsp_auth_get_property; + gobject_class->set_property = gst_rtsp_auth_set_property; + gobject_class->finalize = gst_rtsp_auth_finalize; + + klass->authenticate = default_authenticate; + klass->check = default_check; + + GST_DEBUG_CATEGORY_INIT (rtsp_auth_debug, "rtspauth", 0, "GstRTSPAuth"); +} + +static void +gst_rtsp_auth_init (GstRTSPAuth * auth) +{ + GstRTSPAuthPrivate *priv; + + auth->priv = priv = GST_RTSP_AUTH_GET_PRIVATE (auth); + + g_mutex_init (&priv->lock); + + priv->basic = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, + (GDestroyNotify) gst_rtsp_token_unref); + + /* bitwise or of all methods that need authentication */ + priv->methods = 0; +} + +static void +gst_rtsp_auth_finalize (GObject * obj) +{ + GstRTSPAuth *auth = GST_RTSP_AUTH (obj); + GstRTSPAuthPrivate *priv = auth->priv; + + GST_INFO ("finalize auth %p", auth); + + if (priv->certificate) + g_object_unref (priv->certificate); + g_hash_table_unref (priv->basic); + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (gst_rtsp_auth_parent_class)->finalize (obj); +} + +static void +gst_rtsp_auth_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + switch (propid) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_auth_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + switch (propid) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +/** + * gst_rtsp_auth_new: + * + * Create a new #GstRTSPAuth instance. + * + * Returns: (transfer full): a new #GstRTSPAuth + */ +GstRTSPAuth * +gst_rtsp_auth_new (void) +{ + GstRTSPAuth *result; + + result = g_object_new (GST_TYPE_RTSP_AUTH, NULL); + + return result; +} + +/** + * gst_rtsp_auth_set_tls_certificate: + * @auth: a #GstRTSPAuth + * @cert: (transfer none) (allow-none): a #GTlsCertificate + * + * Set the TLS certificate for the auth. Client connections will only + * be accepted when TLS is negotiated. + */ +void +gst_rtsp_auth_set_tls_certificate (GstRTSPAuth * auth, GTlsCertificate * cert) +{ + GstRTSPAuthPrivate *priv; + GTlsCertificate *old; + + g_return_if_fail (GST_IS_RTSP_AUTH (auth)); + + priv = auth->priv; + + if (cert) + g_object_ref (cert); + + g_mutex_lock (&priv->lock); + old = priv->certificate; + priv->certificate = cert; + g_mutex_unlock (&priv->lock); + + if (old) + g_object_unref (old); +} + +/** + * gst_rtsp_auth_get_tls_certificate: + * @auth: a #GstRTSPAuth + * + * Get the #GTlsCertificate used for negotiating TLS @auth. + * + * Returns: (transfer full): the #GTlsCertificate of @auth. g_object_unref() after + * usage. + */ +GTlsCertificate * +gst_rtsp_auth_get_tls_certificate (GstRTSPAuth * auth) +{ + GstRTSPAuthPrivate *priv; + GTlsCertificate *result; + + g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL); + + priv = auth->priv; + + g_mutex_lock (&priv->lock); + if ((result = priv->certificate)) + g_object_ref (result); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_auth_set_default_token: + * @auth: a #GstRTSPAuth + * @token: (transfer none) (allow-none): a #GstRTSPToken + * + * Set the default #GstRTSPToken to @token in @auth. The default token will + * be used for unauthenticated users. + */ +void +gst_rtsp_auth_set_default_token (GstRTSPAuth * auth, GstRTSPToken * token) +{ + GstRTSPAuthPrivate *priv; + GstRTSPToken *old; + + g_return_if_fail (GST_IS_RTSP_AUTH (auth)); + + priv = auth->priv; + + if (token) + gst_rtsp_token_ref (token); + + g_mutex_lock (&priv->lock); + old = priv->default_token; + priv->default_token = token; + g_mutex_unlock (&priv->lock); + + if (old) + gst_rtsp_token_unref (old); +} + +/** + * gst_rtsp_auth_get_default_token: + * @auth: a #GstRTSPAuth + * + * Get the default token for @auth. This token will be used for unauthenticated + * users. + * + * Returns: (transfer full): the #GstRTSPToken of @auth. gst_rtsp_token_unref() after + * usage. + */ +GstRTSPToken * +gst_rtsp_auth_get_default_token (GstRTSPAuth * auth) +{ + GstRTSPAuthPrivate *priv; + GstRTSPToken *result; + + g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL); + + priv = auth->priv; + + g_mutex_lock (&priv->lock); + if ((result = priv->default_token)) + gst_rtsp_token_ref (result); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_auth_add_basic: + * @auth: a #GstRTSPAuth + * @basic: the basic token + * @token: (transfer none): authorisation token + * + * Add a basic token for the default authentication algorithm that + * enables the client with privileges listed in @token. + */ +void +gst_rtsp_auth_add_basic (GstRTSPAuth * auth, const gchar * basic, + GstRTSPToken * token) +{ + GstRTSPAuthPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_AUTH (auth)); + g_return_if_fail (basic != NULL); + g_return_if_fail (GST_IS_RTSP_TOKEN (token)); + + priv = auth->priv; + + g_mutex_lock (&priv->lock); + g_hash_table_replace (priv->basic, g_strdup (basic), + gst_rtsp_token_ref (token)); + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_auth_remove_basic: + * @auth: a #GstRTSPAuth + * @basic: (transfer none): the basic token + * + * Add a basic token for the default authentication algorithm that + * enables the client with privileges from @authgroup. + */ +void +gst_rtsp_auth_remove_basic (GstRTSPAuth * auth, const gchar * basic) +{ + GstRTSPAuthPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_AUTH (auth)); + g_return_if_fail (basic != NULL); + + priv = auth->priv; + + g_mutex_lock (&priv->lock); + g_hash_table_remove (priv->basic, basic); + g_mutex_unlock (&priv->lock); +} + +static gboolean +default_authenticate (GstRTSPAuth * auth, GstRTSPContext * ctx) +{ + GstRTSPAuthPrivate *priv = auth->priv; + GstRTSPResult res; + gchar *authorization; + + GST_DEBUG_OBJECT (auth, "authenticate"); + + g_mutex_lock (&priv->lock); + /* FIXME, need to ref but we have no way to unref when the ctx is + * popped */ + ctx->token = priv->default_token; + g_mutex_unlock (&priv->lock); + + res = + gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_AUTHORIZATION, + &authorization, 0); + if (res < 0) + goto no_auth; + + /* parse type */ + if (g_ascii_strncasecmp (authorization, "basic ", 6) == 0) { + GstRTSPToken *token; + + GST_DEBUG_OBJECT (auth, "check Basic auth"); + g_mutex_lock (&priv->lock); + if ((token = g_hash_table_lookup (priv->basic, &authorization[6]))) { + GST_DEBUG_OBJECT (auth, "setting token %p", token); + ctx->token = token; + } + g_mutex_unlock (&priv->lock); + } else if (g_ascii_strncasecmp (authorization, "digest ", 7) == 0) { + GST_DEBUG_OBJECT (auth, "check Digest auth"); + /* not implemented yet */ + } + return TRUE; + +no_auth: + { + GST_DEBUG_OBJECT (auth, "no authorization header found"); + return TRUE; + } +} + +static void +send_response (GstRTSPAuth * auth, GstRTSPStatusCode code, GstRTSPContext * ctx) +{ + gst_rtsp_message_init_response (ctx->response, code, + gst_rtsp_status_as_text (code), ctx->request); + + if (code == GST_RTSP_STS_UNAUTHORIZED) { + /* we only have Basic for now */ + gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_WWW_AUTHENTICATE, + "Basic realm=\"GStreamer RTSP Server\""); + } + gst_rtsp_client_send_message (ctx->client, ctx->session, ctx->response); +} + +static gboolean +ensure_authenticated (GstRTSPAuth * auth, GstRTSPContext * ctx) +{ + GstRTSPAuthClass *klass; + + klass = GST_RTSP_AUTH_GET_CLASS (auth); + + /* we need a token to check */ + if (ctx->token == NULL) { + if (klass->authenticate) { + if (!klass->authenticate (auth, ctx)) + goto authenticate_failed; + } + } + if (ctx->token == NULL) + goto no_auth; + + return TRUE; + +/* ERRORS */ +authenticate_failed: + { + GST_DEBUG_OBJECT (auth, "authenticate failed"); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx); + return FALSE; + } +no_auth: + { + GST_DEBUG_OBJECT (auth, "no authorization token found"); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx); + return FALSE; + } +} + +/* new connection */ +static gboolean +check_connect (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check) +{ + GstRTSPAuthPrivate *priv = auth->priv; + + if (priv->certificate) { + GTlsConnection *tls; + + /* configure the connection */ + tls = gst_rtsp_connection_get_tls (ctx->conn, NULL); + g_tls_connection_set_certificate (tls, priv->certificate); + } + return TRUE; +} + +/* check url and methods */ +static gboolean +check_url (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check) +{ + GstRTSPAuthPrivate *priv = auth->priv; + + if ((ctx->method & priv->methods) != 0) + if (!ensure_authenticated (auth, ctx)) + goto not_authenticated; + + return TRUE; + + /* ERRORS */ +not_authenticated: + { + return FALSE; + } +} + +/* check access to media factory */ +static gboolean +check_factory (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check) +{ + const gchar *role; + GstRTSPPermissions *perms; + + if (!ensure_authenticated (auth, ctx)) + return FALSE; + + if (!(role = gst_rtsp_token_get_string (ctx->token, + GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE))) + goto no_media_role; + if (!(perms = gst_rtsp_media_factory_get_permissions (ctx->factory))) + goto no_permissions; + + if (g_str_equal (check, GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS)) { + if (!gst_rtsp_permissions_is_allowed (perms, role, + GST_RTSP_PERM_MEDIA_FACTORY_ACCESS)) + goto no_access; + } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT)) { + if (!gst_rtsp_permissions_is_allowed (perms, role, + GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT)) + goto no_construct; + } + + gst_rtsp_permissions_unref (perms); + + return TRUE; + + /* ERRORS */ +no_media_role: + { + GST_DEBUG_OBJECT (auth, "no media factory role found"); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx); + return FALSE; + } +no_permissions: + { + GST_DEBUG_OBJECT (auth, "no permissions on media factory found"); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx); + return FALSE; + } +no_access: + { + GST_DEBUG_OBJECT (auth, "no permissions to access media factory"); + gst_rtsp_permissions_unref (perms); + send_response (auth, GST_RTSP_STS_NOT_FOUND, ctx); + return FALSE; + } +no_construct: + { + GST_DEBUG_OBJECT (auth, "no permissions to construct media factory"); + gst_rtsp_permissions_unref (perms); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx); + return FALSE; + } +} + +static gboolean +check_client_settings (GstRTSPAuth * auth, GstRTSPContext * ctx, + const gchar * check) +{ + if (!ensure_authenticated (auth, ctx)) + return FALSE; + + return gst_rtsp_token_is_allowed (ctx->token, + GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS); +} + +static gboolean +default_check (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check) +{ + gboolean res = FALSE; + + /* FIXME, use hastable or so */ + if (g_str_equal (check, GST_RTSP_AUTH_CHECK_CONNECT)) { + res = check_connect (auth, ctx, check); + } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_URL)) { + res = check_url (auth, ctx, check); + } else if (g_str_has_prefix (check, "auth.check.media.factory.")) { + res = check_factory (auth, ctx, check); + } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS)) { + res = check_client_settings (auth, ctx, check); + } + return res; +} + +static gboolean +no_auth_check (const gchar * check) +{ + gboolean res; + + if (g_str_equal (check, GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS)) + res = FALSE; + else + res = TRUE; + + return res; +} + +/** + * gst_rtsp_auth_check: + * @check: the item to check + * + * Check if @check is allowed in the current context. + * + * Returns: FALSE if check failed. + */ +gboolean +gst_rtsp_auth_check (const gchar * check) +{ + gboolean result = FALSE; + GstRTSPAuthClass *klass; + GstRTSPContext *ctx; + GstRTSPAuth *auth; + + g_return_val_if_fail (check != NULL, FALSE); + + if (!(ctx = gst_rtsp_context_get_current ())) + goto no_context; + + /* no auth, we don't need to check */ + if (!(auth = ctx->auth)) + return no_auth_check (check); + + klass = GST_RTSP_AUTH_GET_CLASS (auth); + + GST_DEBUG_OBJECT (auth, "check authorization '%s'", check); + + if (klass->check) + result = klass->check (auth, ctx, check); + + return result; + + /* ERRORS */ +no_context: + { + GST_ERROR ("no context found"); + return FALSE; + } +} + +/** + * gst_rtsp_auth_make_basic: + * @user: a userid + * @pass: a password + * + * Construct a Basic authorisation token from @user and @pass. + * + * Returns: (transfer full): the base64 encoding of the string @user:@pass. + * g_free() after usage. + */ +gchar * +gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass) +{ + gchar *user_pass; + gchar *result; + + g_return_val_if_fail (user != NULL, NULL); + g_return_val_if_fail (pass != NULL, NULL); + + user_pass = g_strjoin (":", user, pass, NULL); + result = g_base64_encode ((guchar *) user_pass, strlen (user_pass)); + g_free (user_pass); + + return result; +} diff --git a/gst/rtsp-server/rtsp-auth.h b/gst/rtsp-server/rtsp-auth.h new file mode 100644 index 0000000..cb281f0 --- /dev/null +++ b/gst/rtsp-server/rtsp-auth.h @@ -0,0 +1,173 @@ +/* GStreamer + * Copyright (C) 2010 Wim Taymans + * + * 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. + */ + +#include + +#ifndef __GST_RTSP_AUTH_H__ +#define __GST_RTSP_AUTH_H__ + +typedef struct _GstRTSPAuth GstRTSPAuth; +typedef struct _GstRTSPAuthClass GstRTSPAuthClass; +typedef struct _GstRTSPAuthPrivate GstRTSPAuthPrivate; + +#include "rtsp-client.h" +#include "rtsp-token.h" + +G_BEGIN_DECLS + +#define GST_TYPE_RTSP_AUTH (gst_rtsp_auth_get_type ()) +#define GST_IS_RTSP_AUTH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_AUTH)) +#define GST_IS_RTSP_AUTH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_AUTH)) +#define GST_RTSP_AUTH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_AUTH, GstRTSPAuthClass)) +#define GST_RTSP_AUTH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_AUTH, GstRTSPAuth)) +#define GST_RTSP_AUTH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_AUTH, GstRTSPAuthClass)) +#define GST_RTSP_AUTH_CAST(obj) ((GstRTSPAuth*)(obj)) +#define GST_RTSP_AUTH_CLASS_CAST(klass) ((GstRTSPAuthClass*)(klass)) + +/** + * GstRTSPAuth: + * + * The authentication structure. + */ +struct _GstRTSPAuth { + GObject parent; + + /*< private >*/ + GstRTSPAuthPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPAuthClass: + * @authenticate: check the authentication of a client. The default implementation + * checks if the authentication in the header matches one of the basic + * authentication tokens. This function should set the authgroup field + * in the context. + * @check: check if a resource can be accessed. this function should + * call authenticate to authenticate the client when needed. The method + * should also construct and send an appropriate response message on + * error. + * + * The authentication class. + */ +struct _GstRTSPAuthClass { + GObjectClass parent_class; + + gboolean (*authenticate) (GstRTSPAuth *auth, GstRTSPContext *ctx); + gboolean (*check) (GstRTSPAuth *auth, GstRTSPContext *ctx, + const gchar *check); + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_rtsp_auth_get_type (void); + +GstRTSPAuth * gst_rtsp_auth_new (void); + +void gst_rtsp_auth_set_tls_certificate (GstRTSPAuth *auth, GTlsCertificate *cert); +GTlsCertificate * gst_rtsp_auth_get_tls_certificate (GstRTSPAuth *auth); + +void gst_rtsp_auth_set_default_token (GstRTSPAuth *auth, GstRTSPToken *token); +GstRTSPToken * gst_rtsp_auth_get_default_token (GstRTSPAuth *auth); + +void gst_rtsp_auth_add_basic (GstRTSPAuth *auth, const gchar * basic, + GstRTSPToken *token); +void gst_rtsp_auth_remove_basic (GstRTSPAuth *auth, const gchar * basic); + +gboolean gst_rtsp_auth_check (const gchar *check); + + +/* helpers */ +gchar * gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass); + +/* checks */ +/** + * GST_RTSP_AUTH_CHECK_CONNECT: + * + * Check a new connection + */ +#define GST_RTSP_AUTH_CHECK_CONNECT "auth.check.connect" +/** + * GST_RTSP_AUTH_CHECK_URL: + * + * Check the URL and methods + */ +#define GST_RTSP_AUTH_CHECK_URL "auth.check.url" +/** + * GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS: + * + * Check if access is allowed to a factory. + * When access is not allowed an 404 Not Found is sent in the response. + */ +#define GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS "auth.check.media.factory.access" +/** + * GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT: + * + * Check if media can be constructed from a media factory + * A response should be sent on error. + */ +#define GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT "auth.check.media.factory.construct" +/** + * GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS: + * + * Check if the client can specify TTL, destination and + * port pair in multicast. No response is sent when the check returns + * %FALSE. + */ +#define GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS "auth.check.transport.client-settings" + + +/* tokens */ +/** + * GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE: + * + * G_TYPE_STRING, the role to use when dealing with media factories + * + * The default #GstRTSPAuth object uses this string in the token to find the + * role of the media factory. It will then retrieve the #GstRTSPPermissions of + * the media factory and retrieve the role with the same name. + */ +#define GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE "media.factory.role" +/** + * GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS: + * + * G_TYPE_BOOLEAN, %TRUE if the client can specify TTL, destination and + * port pair in multicast. + */ +#define GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS "transport.client-settings" + +/* permissions */ +/** + * GST_RTSP_PERM_MEDIA_FACTORY_ACCESS: + * + * G_TYPE_BOOLEAN, %TRUE if the media can be accessed, %FALSE will + * return a 404 Not Found error when trying to access the media. + */ +#define GST_RTSP_PERM_MEDIA_FACTORY_ACCESS "media.factory.access" +/** + * GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT: + * + * G_TYPE_BOOLEAN, %TRUE if the media can be constructed, %FALSE will + * return a 404 Not Found error when trying to access the media. + */ +#define GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT "media.factory.construct" + +G_END_DECLS + +#endif /* __GST_RTSP_AUTH_H__ */ diff --git a/gst/rtsp-server/rtsp-client-wfd.c b/gst/rtsp-server/rtsp-client-wfd.c new file mode 100644 index 0000000..e594160 --- /dev/null +++ b/gst/rtsp-server/rtsp-client-wfd.c @@ -0,0 +1,2950 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-client + * @short_description: A client connection state + * @see_also: #GstRTSPServer, #GstRTSPThreadPool + * + * The client object handles the connection with a client for as long as a TCP + * connection is open. + * + * A #GstRTSPWFDClient is created by #GstRTSPServer when a new connection is + * accepted and it inherits the #GstRTSPMountPoints, #GstRTSPSessionPool, + * #GstRTSPAuth and #GstRTSPThreadPool from the server. + * + * The client connection should be configured with the #GstRTSPConnection using + * gst_rtsp_wfd_client_set_connection() before it can be attached to a #GMainContext + * using gst_rtsp_wfd_client_attach(). From then on the client will handle requests + * on the connection. + * + * Use gst_rtsp_wfd_client_session_filter() to iterate or modify all the + * #GstRTSPSession objects managed by the client object. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include +#include + +#include "rtsp-client-wfd.h" +#include "rtsp-media-factory-wfd.h" +#include "rtsp-sdp.h" +#include "rtsp-params.h" + +#define GST_RTSP_WFD_CLIENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_WFD_CLIENT, GstRTSPWFDClientPrivate)) + +typedef struct _GstRTSPClientRTPStats GstRTSPClientRTPStats; + +struct _GstRTSPClientRTPStats { + GstRTSPStream *stream; + guint64 last_sent_bytes; + guint64 sent_bytes; + guint last_seqnum; + guint seqnum; + + /* Info in RR (Receiver Report) */ + guint8 fraction_lost; + guint32 cumulative_lost_num; + guint16 max_seqnum; + guint32 arrival_jitter; + guint32 lsr; + guint32 dlsr; + guint32 rtt; + guint resent_packets; +}; + +struct _GstRTSPWFDClientPrivate +{ + GstRTSPWFDClientSendFunc send_func; /* protected by send_lock */ + gpointer send_data; /* protected by send_lock */ + GDestroyNotify send_notify; /* protected by send_lock */ + + /* used to cache the media in the last requested DESCRIBE so that + * we can pick it up in the next SETUP immediately */ + gchar *path; + GstRTSPMedia *media; + + GList *transports; + GList *sessions; + + guint8 m1_done; + guint8 m3_done; + guint8 m4_done; + + /* Host's URL info */ + gchar *host_address; + + /* Parameters for WIFI-DISPLAY */ + guint caCodec; + guint8 audio_codec; + guint cFreq; + guint cChanels; + guint cBitwidth; + guint caLatency; + guint cvCodec; + guint cNative; + guint64 cNativeResolution; + guint64 video_resolution_supported; + gint video_native_resolution; + guint64 cCEAResolution; + guint64 cVESAResolution; + guint64 cHHResolution; + guint cProfile; + guint cLevel; + guint32 cMaxHeight; + guint32 cMaxWidth; + guint32 cFramerate; + guint32 cInterleaved; + guint32 cmin_slice_size; + guint32 cslice_enc_params; + guint cframe_rate_control; + guint cvLatency; + guint ctrans; + guint cprofile; + guint clowertrans; + guint32 crtp_port0; + guint32 crtp_port1; + + gboolean protection_enabled; + GstWFDHDCPProtection hdcp_version; + guint32 hdcp_tcpport; + + gboolean edid_supported; + guint32 edid_hres; + guint32 edid_vres; + + gboolean keep_alive_flag; + GMutex keep_alive_lock; + + /* RTP statistics */ + GstRTSPClientRTPStats stats; + GMutex stats_lock; + guint stats_timer_id; + gboolean rtcp_stats_enabled; +}; + +#define DEFAULT_WFD_TIMEOUT 60 +#define WFD_MOUNT_POINT "/wfd1.0/streamid=0" + +enum +{ + SIGNAL_WFD_OPTIONS_REQUEST, + SIGNAL_WFD_GET_PARAMETER_REQUEST, + SIGNAL_WFD_LAST +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_wfd_client_debug); +#define GST_CAT_DEFAULT rtsp_wfd_client_debug + +static guint gst_rtsp_client_wfd_signals[SIGNAL_WFD_LAST] = { 0 }; + +static void gst_rtsp_wfd_client_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_wfd_client_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); +static void gst_rtsp_wfd_client_finalize (GObject * obj); + +static gboolean handle_wfd_options_request (GstRTSPClient * client, + GstRTSPContext * ctx); +static gboolean handle_wfd_set_param_request (GstRTSPClient * client, + GstRTSPContext * ctx); +static gboolean handle_wfd_get_param_request (GstRTSPClient * client, + GstRTSPContext * ctx); + +static void send_generic_wfd_response (GstRTSPWFDClient * client, + GstRTSPStatusCode code, GstRTSPContext * ctx); +static gchar *wfd_make_path_from_uri (GstRTSPClient * client, + const GstRTSPUrl * uri); +static void wfd_options_request_done (GstRTSPWFDClient * client, GstRTSPContext *ctx); +static void wfd_get_param_request_done (GstRTSPWFDClient * client, GstRTSPContext *ctx); +static void handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx); +static void handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx); +static void wfd_set_keep_alive_condition(GstRTSPWFDClient * client); +static gboolean wfd_ckeck_keep_alive_response (gpointer userdata); +static gboolean keep_alive_condition(gpointer userdata); +static gboolean wfd_configure_client_media (GstRTSPClient * client, GstRTSPMedia * media, + GstRTSPStream * stream, GstRTSPContext * ctx); + +GstRTSPResult prepare_trigger_request (GstRTSPWFDClient * client, + GstRTSPMessage * request, GstWFDTriggerType trigger_type, gchar * url); + +GstRTSPResult prepare_request (GstRTSPWFDClient * client, + GstRTSPMessage * request, GstRTSPMethod method, gchar * url); + +void +send_request (GstRTSPWFDClient * client, GstRTSPSession * session, + GstRTSPMessage * request); + +GstRTSPResult +prepare_response (GstRTSPWFDClient * client, GstRTSPMessage * request, + GstRTSPMessage * response, GstRTSPMethod method); + +static GstRTSPResult handle_M1_message (GstRTSPWFDClient * client); +static GstRTSPResult handle_M3_message (GstRTSPWFDClient * client); +static GstRTSPResult handle_M4_message (GstRTSPWFDClient * client); +static GstRTSPResult handle_M16_message (GstRTSPWFDClient * client); + +G_DEFINE_TYPE (GstRTSPWFDClient, gst_rtsp_wfd_client, GST_TYPE_RTSP_CLIENT); + +static void +gst_rtsp_wfd_client_class_init (GstRTSPWFDClientClass * klass) +{ + GObjectClass *gobject_class; + GstRTSPClientClass *rtsp_client_class; + + g_type_class_add_private (klass, sizeof (GstRTSPWFDClientPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + rtsp_client_class = GST_RTSP_CLIENT_CLASS (klass); + + gobject_class->get_property = gst_rtsp_wfd_client_get_property; + gobject_class->set_property = gst_rtsp_wfd_client_set_property; + gobject_class->finalize = gst_rtsp_wfd_client_finalize; + + //klass->create_sdp = create_sdp; + //klass->configure_client_transport = default_configure_client_transport; + //klass->params_set = default_params_set; + //klass->params_get = default_params_get; + + rtsp_client_class->handle_options_request = handle_wfd_options_request; + rtsp_client_class->handle_set_param_request = handle_wfd_set_param_request; + rtsp_client_class->handle_get_param_request = handle_wfd_get_param_request; + rtsp_client_class->make_path_from_uri = wfd_make_path_from_uri; + rtsp_client_class->configure_client_media = wfd_configure_client_media; + + rtsp_client_class->handle_response = handle_wfd_response; + rtsp_client_class->play_request = handle_wfd_play; + + gst_rtsp_client_wfd_signals[SIGNAL_WFD_OPTIONS_REQUEST] = + g_signal_new ("wfd-options-request", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass, + wfd_options_request), NULL, NULL, g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT); + + gst_rtsp_client_wfd_signals[SIGNAL_WFD_GET_PARAMETER_REQUEST] = + g_signal_new ("wfd-get-parameter-request", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass, + wfd_get_param_request), NULL, NULL, g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT); + + klass->wfd_options_request = wfd_options_request_done; + klass->wfd_get_param_request = wfd_get_param_request_done; + + GST_DEBUG_CATEGORY_INIT (rtsp_wfd_client_debug, "rtspwfdclient", 0, + "GstRTSPWFDClient"); +} + +static void +gst_rtsp_wfd_client_init (GstRTSPWFDClient * client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + g_return_if_fail (priv != NULL); + + client->priv = priv; + priv->protection_enabled = FALSE; + priv->video_native_resolution = GST_WFD_VIDEO_CEA_RESOLUTION; + priv->video_resolution_supported = GST_WFD_CEA_640x480P60; + priv->audio_codec = GST_WFD_AUDIO_AAC; + priv->keep_alive_flag = FALSE; + + g_mutex_init (&priv->keep_alive_lock); + g_mutex_init (&priv->stats_lock); + + priv->host_address = NULL; + + priv->stats_timer_id = -1; + priv->rtcp_stats_enabled = FALSE; + memset (&priv->stats, 0x00, sizeof (GstRTSPClientRTPStats)); + + GST_INFO_OBJECT (client, "Client is initialized"); +} + +/* A client is finalized when the connection is broken */ +static void +gst_rtsp_wfd_client_finalize (GObject * obj) +{ + GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (obj); + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + g_return_if_fail (GST_IS_RTSP_WFD_CLIENT (obj)); + g_return_if_fail (priv != NULL); + + GST_INFO ("finalize client %p", client); + + if (priv->host_address) + g_free (priv->host_address); + + if (priv->stats_timer_id > 0) + g_source_remove(priv->stats_timer_id); + + g_mutex_clear (&priv->keep_alive_lock); + g_mutex_clear (&priv->stats_lock); + G_OBJECT_CLASS (gst_rtsp_wfd_client_parent_class)->finalize (obj); +} + +static void +gst_rtsp_wfd_client_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + //GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (object); + + switch (propid) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_wfd_client_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + //GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (object); + + switch (propid) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +/** + * gst_rtsp_wfd_client_new: + * + * Create a new #GstRTSPWFDClient instance. + * + * Returns: a new #GstRTSPWFDClient + */ +GstRTSPWFDClient * +gst_rtsp_wfd_client_new (void) +{ + GstRTSPWFDClient *result; + + result = g_object_new (GST_TYPE_RTSP_WFD_CLIENT, NULL); + + return result; +} + +void +gst_rtsp_wfd_client_start_wfd (GstRTSPWFDClient * client) +{ + GstRTSPResult res = GST_RTSP_OK; + GST_INFO_OBJECT (client, "gst_rtsp_wfd_client_start_wfd"); + + res = handle_M1_message (client); + if (res < GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "handle_M1_message failed : %d", res); + } + + return; +} + +static gboolean +wfd_display_rtp_stats (gpointer userdata) +{ + guint16 seqnum = 0; + guint64 bytes = 0; + + GstRTSPWFDClient *client = NULL; + GstRTSPWFDClientPrivate *priv = NULL; + + client = (GstRTSPWFDClient *) userdata; + priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + if (!priv) { + GST_ERROR("No priv"); + return FALSE; + } + + g_mutex_lock(&priv->stats_lock); + + seqnum = gst_rtsp_stream_get_current_seqnum (priv->stats.stream); + bytes = gst_rtsp_stream_get_udp_sent_bytes (priv->stats.stream); + + GST_INFO ("----------------------------------------------------\n"); + GST_INFO ("Sent RTP packets : %d", seqnum - priv->stats.last_seqnum); + GST_INFO ("Sent Bytes of RTP packets : %lld bytes", bytes - priv->stats.last_sent_bytes); + + priv->stats.last_seqnum = seqnum; + priv->stats.last_sent_bytes = bytes; + + if (priv->rtcp_stats_enabled) { + GST_INFO ("Fraction Lost: %d", priv->stats.fraction_lost); + GST_INFO ("Cumulative number of packets lost: %d", priv->stats.cumulative_lost_num); + GST_INFO ("Extended highest sequence number received: %d", priv->stats.max_seqnum); + GST_INFO ("Interarrival Jitter: %d", priv->stats.arrival_jitter); + GST_INFO ("Round trip time : %d", priv->stats.rtt); + } + + GST_INFO ("----------------------------------------------------\n"); + + g_mutex_unlock(&priv->stats_lock); + + return TRUE; +} + +static void +on_rtcp_stats (GstRTSPStream *stream, GstStructure *stats, GstRTSPClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + guint fraction_lost, exthighestseq, jitter, lsr, dlsr, rtt; + gint packetslost; + + if (!priv) return; + + g_mutex_lock(&priv->stats_lock); + + gst_structure_get_uint (stats, "rb-fractionlost", &fraction_lost); + gst_structure_get_int (stats, "rb-packetslost", &packetslost); + gst_structure_get_uint (stats, "rb-exthighestseq", &exthighestseq); + gst_structure_get_uint (stats, "rb-jitter", &jitter); + gst_structure_get_uint (stats, "rb-lsr", &lsr); + gst_structure_get_uint (stats, "rb-dlsr", &dlsr); + gst_structure_get_uint (stats, "rb-round-trip", &rtt); + + if (!priv->rtcp_stats_enabled) + priv->rtcp_stats_enabled = TRUE; + + priv->stats.stream = stream; + priv->stats.fraction_lost = (guint8)fraction_lost; + priv->stats.cumulative_lost_num += (guint32)fraction_lost; + priv->stats.max_seqnum = (guint16)exthighestseq; + priv->stats.arrival_jitter = (guint32)jitter; + priv->stats.lsr = (guint32)lsr; + priv->stats.dlsr = (guint32)dlsr; + priv->stats.rtt = (guint32)rtt; + + g_mutex_unlock(&priv->stats_lock); +} + +static gboolean +wfd_configure_client_media (GstRTSPClient * client, GstRTSPMedia * media, + GstRTSPStream * stream, GstRTSPContext * ctx) +{ + if (stream) { + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + if (priv) + priv->stats.stream = stream; + g_signal_connect (stream, "rtcp-statistics", (GCallback) on_rtcp_stats, client); + } + + return GST_RTSP_CLIENT_CLASS (gst_rtsp_wfd_client_parent_class)->configure_client_media (client, media, stream, ctx); +} +static void +wfd_options_request_done (GstRTSPWFDClient * client, GstRTSPContext *ctx) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPWFDClientClass *klass = GST_RTSP_WFD_CLIENT_GET_CLASS (client); + + g_return_if_fail (klass != NULL); + + GST_INFO_OBJECT (client, "M2 done.."); + + res = handle_M3_message (client); + if (res < GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "handle_M3_message failed : %d", res); + } + + if (klass->prepare_resource) { + klass->prepare_resource (client, ctx); + } + + return; +} + +static void +wfd_get_param_request_done (GstRTSPWFDClient * client, GstRTSPContext *ctx) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + GstRTSPWFDClientClass *klass = GST_RTSP_WFD_CLIENT_GET_CLASS (client); + + g_return_if_fail (priv != NULL && klass != NULL); + + priv->m3_done = TRUE; + GST_INFO_OBJECT (client, "M3 done.."); + + res = handle_M4_message (client); + if (res < GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "handle_M4_message failed : %d", res); + } + + if (klass->confirm_resource) { + klass->confirm_resource (client, ctx); + } + + return; +} + +static guint +wfd_get_prefered_audio_codec (guint8 srcAudioCodec, + guint sinkAudioCodec) +{ + int i = 0; + guint codec = 0; + for (i = 0; i < 8; i++) { + if (((sinkAudioCodec << i) & 0x80) + && ((srcAudioCodec << i) & 0x80)) { + codec = (0x01 << (7 - i)); + break; + } + } + return codec; +} + +static guint64 +wfd_get_prefered_resolution (guint64 srcResolution, + guint64 sinkResolution, + GstWFDVideoNativeResolution native, + guint32 * cMaxWidth, + guint32 * cMaxHeight, guint32 * cFramerate, guint32 * interleaved) +{ + int i = 0; + guint64 resolution = 0; + for (i = 0; i < 32; i++) { + if (((sinkResolution << i) & 0x80000000) + && ((srcResolution << i) & 0x80000000)) { + resolution = ((guint64) 0x00000001 << (31 - i)); + break; + } + } + switch (native) { + case GST_WFD_VIDEO_CEA_RESOLUTION: + { + switch (resolution) { + case GST_WFD_CEA_640x480P60: + *cMaxWidth = 640; + *cMaxHeight = 480; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_CEA_720x480P60: + *cMaxWidth = 720; + *cMaxHeight = 480; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_CEA_720x480I60: + *cMaxWidth = 720; + *cMaxHeight = 480; + *cFramerate = 60; + *interleaved = 1; + break; + case GST_WFD_CEA_720x576P50: + *cMaxWidth = 720; + *cMaxHeight = 576; + *cFramerate = 50; + *interleaved = 0; + break; + case GST_WFD_CEA_720x576I50: + *cMaxWidth = 720; + *cMaxHeight = 576; + *cFramerate = 50; + *interleaved = 1; + break; + case GST_WFD_CEA_1280x720P30: + *cMaxWidth = 1280; + *cMaxHeight = 720; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_CEA_1280x720P60: + *cMaxWidth = 1280; + *cMaxHeight = 720; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_CEA_1920x1080P30: + *cMaxWidth = 1920; + *cMaxHeight = 1080; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_CEA_1920x1080P60: + *cMaxWidth = 1920; + *cMaxHeight = 1080; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_CEA_1920x1080I60: + *cMaxWidth = 1920; + *cMaxHeight = 1080; + *cFramerate = 60; + *interleaved = 1; + break; + case GST_WFD_CEA_1280x720P25: + *cMaxWidth = 1280; + *cMaxHeight = 720; + *cFramerate = 25; + *interleaved = 0; + break; + case GST_WFD_CEA_1280x720P50: + *cMaxWidth = 1280; + *cMaxHeight = 720; + *cFramerate = 50; + *interleaved = 0; + break; + case GST_WFD_CEA_1920x1080P25: + *cMaxWidth = 1920; + *cMaxHeight = 1080; + *cFramerate = 25; + *interleaved = 0; + break; + case GST_WFD_CEA_1920x1080P50: + *cMaxWidth = 1920; + *cMaxHeight = 1080; + *cFramerate = 50; + *interleaved = 0; + break; + case GST_WFD_CEA_1920x1080I50: + *cMaxWidth = 1920; + *cMaxHeight = 1080; + *cFramerate = 50; + *interleaved = 1; + break; + case GST_WFD_CEA_1280x720P24: + *cMaxWidth = 1280; + *cMaxHeight = 720; + *cFramerate = 24; + *interleaved = 0; + break; + case GST_WFD_CEA_1920x1080P24: + *cMaxWidth = 1920; + *cMaxHeight = 1080; + *cFramerate = 24; + *interleaved = 0; + break; + default: + *cMaxWidth = 0; + *cMaxHeight = 0; + *cFramerate = 0; + *interleaved = 0; + break; + } + } + break; + case GST_WFD_VIDEO_VESA_RESOLUTION: + { + switch (resolution) { + case GST_WFD_VESA_800x600P30: + *cMaxWidth = 800; + *cMaxHeight = 600; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_800x600P60: + *cMaxWidth = 800; + *cMaxHeight = 600; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1024x768P30: + *cMaxWidth = 1024; + *cMaxHeight = 768; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1024x768P60: + *cMaxWidth = 1024; + *cMaxHeight = 768; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1152x864P30: + *cMaxWidth = 1152; + *cMaxHeight = 864; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1152x864P60: + *cMaxWidth = 1152; + *cMaxHeight = 864; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1280x768P30: + *cMaxWidth = 1280; + *cMaxHeight = 768; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1280x768P60: + *cMaxWidth = 1280; + *cMaxHeight = 768; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1280x800P30: + *cMaxWidth = 1280; + *cMaxHeight = 800; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1280x800P60: + *cMaxWidth = 1280; + *cMaxHeight = 800; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1360x768P30: + *cMaxWidth = 1360; + *cMaxHeight = 768; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1360x768P60: + *cMaxWidth = 1360; + *cMaxHeight = 768; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1366x768P30: + *cMaxWidth = 1366; + *cMaxHeight = 768; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1366x768P60: + *cMaxWidth = 1366; + *cMaxHeight = 768; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1280x1024P30: + *cMaxWidth = 1280; + *cMaxHeight = 1024; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1280x1024P60: + *cMaxWidth = 1280; + *cMaxHeight = 1024; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1400x1050P30: + *cMaxWidth = 1400; + *cMaxHeight = 1050; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1400x1050P60: + *cMaxWidth = 1400; + *cMaxHeight = 1050; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1440x900P30: + *cMaxWidth = 1440; + *cMaxHeight = 900; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1440x900P60: + *cMaxWidth = 1440; + *cMaxHeight = 900; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1600x900P30: + *cMaxWidth = 1600; + *cMaxHeight = 900; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1600x900P60: + *cMaxWidth = 1600; + *cMaxHeight = 900; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1600x1200P30: + *cMaxWidth = 1600; + *cMaxHeight = 1200; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1600x1200P60: + *cMaxWidth = 1600; + *cMaxHeight = 1200; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1680x1024P30: + *cMaxWidth = 1680; + *cMaxHeight = 1024; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1680x1024P60: + *cMaxWidth = 1680; + *cMaxHeight = 1024; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1680x1050P30: + *cMaxWidth = 1680; + *cMaxHeight = 1050; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1680x1050P60: + *cMaxWidth = 1680; + *cMaxHeight = 1050; + *cFramerate = 60; + *interleaved = 0; + break; + case GST_WFD_VESA_1920x1200P30: + *cMaxWidth = 1920; + *cMaxHeight = 1200; + *cFramerate = 30; + *interleaved = 0; + break; + case GST_WFD_VESA_1920x1200P60: + *cMaxWidth = 1920; + *cMaxHeight = 1200; + *cFramerate = 60; + *interleaved = 0; + break; + default: + *cMaxWidth = 0; + *cMaxHeight = 0; + *cFramerate = 0; + *interleaved = 0; + break; + } + } + break; + case GST_WFD_VIDEO_HH_RESOLUTION: + { + *interleaved = 0; + switch (resolution) { + case GST_WFD_HH_800x480P30: + *cMaxWidth = 800; + *cMaxHeight = 480; + *cFramerate = 30; + break; + case GST_WFD_HH_800x480P60: + *cMaxWidth = 800; + *cMaxHeight = 480; + *cFramerate = 60; + break; + case GST_WFD_HH_854x480P30: + *cMaxWidth = 854; + *cMaxHeight = 480; + *cFramerate = 30; + break; + case GST_WFD_HH_854x480P60: + *cMaxWidth = 854; + *cMaxHeight = 480; + *cFramerate = 60; + break; + case GST_WFD_HH_864x480P30: + *cMaxWidth = 864; + *cMaxHeight = 480; + *cFramerate = 30; + break; + case GST_WFD_HH_864x480P60: + *cMaxWidth = 864; + *cMaxHeight = 480; + *cFramerate = 60; + break; + case GST_WFD_HH_640x360P30: + *cMaxWidth = 640; + *cMaxHeight = 360; + *cFramerate = 30; + break; + case GST_WFD_HH_640x360P60: + *cMaxWidth = 640; + *cMaxHeight = 360; + *cFramerate = 60; + break; + case GST_WFD_HH_960x540P30: + *cMaxWidth = 960; + *cMaxHeight = 540; + *cFramerate = 30; + break; + case GST_WFD_HH_960x540P60: + *cMaxWidth = 960; + *cMaxHeight = 540; + *cFramerate = 60; + break; + case GST_WFD_HH_848x480P30: + *cMaxWidth = 848; + *cMaxHeight = 480; + *cFramerate = 30; + break; + case GST_WFD_HH_848x480P60: + *cMaxWidth = 848; + *cMaxHeight = 480; + *cFramerate = 60; + break; + default: + *cMaxWidth = 0; + *cMaxHeight = 0; + *cFramerate = 0; + *interleaved = 0; + break; + } + } + break; + + default: + *cMaxWidth = 0; + *cMaxHeight = 0; + *cFramerate = 0; + *interleaved = 0; + break; + } + return resolution; +} + +static gchar * +wfd_make_path_from_uri (GstRTSPClient * client, const GstRTSPUrl * uri) +{ + gchar *path; + + GST_DEBUG_OBJECT (client, "Got URI host : %s", uri->host); + GST_DEBUG_OBJECT (client, "Got URI abspath : %s", uri->abspath); + + path = g_strdup ("/wfd1.0/streamid=0"); + + return path; +} + +static void +handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client); + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + g_return_if_fail (priv != NULL); + + wfd_set_keep_alive_condition(_client); + + priv->stats_timer_id = g_timeout_add (2000, wfd_display_rtp_stats, _client); +} + +static void +handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPResult res = GST_RTSP_OK; + guint8 *data = NULL; + guint size = 0; + + GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client); + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + g_return_if_fail (priv != NULL); + + GST_INFO_OBJECT (_client, "Handling response.."); + + if (!ctx) { + GST_ERROR_OBJECT (_client, "Context is NULL"); + goto error; + } + + if (!ctx->response) { + GST_ERROR_OBJECT (_client, "Response is NULL"); + goto error; + } + + /* parsing the GET_PARAMTER response */ + res = gst_rtsp_message_get_body (ctx->response, (guint8 **) & data, &size); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (_client, "Failed to get body of response..."); + return; + } + + GST_INFO_OBJECT (_client, "Response body is %d", size); + if (size > 0) { + if (!priv->m3_done) { + GstWFDResult wfd_res; + GstWFDMessage *msg = NULL; + /* Parse M3 response from sink */ + wfd_res = gst_wfd_message_new (&msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to create wfd message..."); + goto error; + } + + wfd_res = gst_wfd_message_init (msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to init wfd message..."); + goto error; + } + + wfd_res = gst_wfd_message_parse_buffer (data, size, msg); + + GST_DEBUG_OBJECT (client, "M3 response server side message body: %s", + gst_wfd_message_as_text (msg)); + + /* Get the audio formats supported by WFDSink */ + if (msg->audio_codecs) { + wfd_res = + gst_wfd_message_get_supported_audio_format (msg, &priv->caCodec, + &priv->cFreq, &priv->cChanels, &priv->cBitwidth, &priv->caLatency); + if (wfd_res != GST_WFD_OK) { + GST_WARNING_OBJECT (client, + "Failed to get wfd support audio formats..."); + goto error; + } + } + + /* Get the Video formats supported by WFDSink */ + wfd_res = + gst_wfd_message_get_supported_video_format (msg, &priv->cvCodec, + &priv->cNative, &priv->cNativeResolution, + (guint64 *) & priv->cCEAResolution, + (guint64 *) & priv->cVESAResolution, + (guint64 *) & priv->cHHResolution, &priv->cProfile, &priv->cLevel, + &priv->cvLatency, &priv->cMaxHeight, &priv->cMaxWidth, + &priv->cmin_slice_size, &priv->cslice_enc_params, + &priv->cframe_rate_control); + if (wfd_res != GST_WFD_OK) { + GST_WARNING_OBJECT (client, + "Failed to get wfd supported video formats..."); + goto error; + } + + if (msg->client_rtp_ports) { + /* Get the RTP ports preferred by WFDSink */ + wfd_res = + gst_wfd_message_get_prefered_rtp_ports (msg, &priv->ctrans, + &priv->cprofile, &priv->clowertrans, &priv->crtp_port0, + &priv->crtp_port1); + if (wfd_res != GST_WFD_OK) { + GST_WARNING_OBJECT (client, + "Failed to get wfd prefered RTP ports..."); + goto error; + } + } + + if (msg->display_edid) { + guint32 edid_block_count = 0; + gchar *edid_payload = NULL; + priv->edid_supported = FALSE; + /* Get the display edid preferred by WFDSink */ + GST_DEBUG_OBJECT (client, "Going to gst_wfd_message_get_display_edid"); + wfd_res = + gst_wfd_message_get_display_edid (msg, &priv->edid_supported, + &edid_block_count, &edid_payload); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to get wfd display edid..."); + goto error; + } + GST_DEBUG_OBJECT (client, " edid supported: %d edid_block_count: %d", + priv->edid_supported, edid_block_count); + if (priv->edid_supported) { + priv->edid_hres = 0; + priv->edid_vres = 0; + priv->edid_hres = + (guint32) (((edid_payload[54 + 4] >> 4) << 8) | edid_payload[54 + + 2]); + priv->edid_vres = + (guint32) (((edid_payload[54 + 7] >> 4) << 8) | edid_payload[54 + + 5]); + GST_DEBUG_OBJECT (client, " edid supported Hres: %d Wres: %d", + priv->edid_hres, priv->edid_vres); + if ((priv->edid_hres < 640) || (priv->edid_vres < 480) + || (priv->edid_hres > 1920) || (priv->edid_vres > 1080)) { + priv->edid_hres = 0; + priv->edid_vres = 0; + priv->edid_supported = FALSE; + GST_WARNING_OBJECT (client, " edid invalid resolutions"); + } + } + } + + if (msg->content_protection) { +#if 0 + /*Get the hdcp version and tcp port by WFDSink */ + wfd_res = + gst_wfd_message_get_contentprotection_type (msg, + &priv->hdcp_version, &priv->hdcp_tcpport); + GST_DEBUG ("hdcp version =%d, tcp port = %d", priv->hdcp_version, + priv->hdcp_tcpport); + if (priv->hdcp_version > 0 && priv->hdcp_tcpport > 0) + priv->protection_enabled = TRUE; + + if (wfd_res != GST_WFD_OK) { + GST_WARNING_OBJECT (client, + "Failed to get wfd content protection..."); + goto error; + } +#else + GST_WARNING_OBJECT (client, "Don't use content protection"); +#endif + } + + g_signal_emit (_client, + gst_rtsp_client_wfd_signals[SIGNAL_WFD_GET_PARAMETER_REQUEST], 0, + ctx); + } else { + /* TODO-WFD: Handle another GET_PARAMETER response with body */ + } + } else if (size == 0) { + if (!priv->m1_done) { + GST_INFO_OBJECT (_client, "M1 response is done"); + priv->m1_done = TRUE; + } else if (!priv->m4_done) { + GST_INFO_OBJECT (_client, "M4 response is done"); + priv->m4_done = TRUE; + + gst_rtsp_wfd_client_trigger_request (_client, WFD_TRIGGER_SETUP); + } else { + g_mutex_lock(&priv->keep_alive_lock); + if (priv->keep_alive_flag == FALSE) { + GST_INFO_OBJECT (_client, "M16 response is done"); + priv->keep_alive_flag = TRUE; + } + g_mutex_unlock(&priv->keep_alive_lock); + } + } + + return; + +error: + return; +} + +static gboolean +handle_wfd_options_request (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPMethod options; + gchar *tmp = NULL; + gchar *str = NULL; + gchar *user_agent = NULL; + + GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client); + + options = GST_RTSP_OPTIONS | + GST_RTSP_PAUSE | + GST_RTSP_PLAY | + GST_RTSP_SETUP | + GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN; + + str = gst_rtsp_options_as_text (options); + + /*append WFD specific method */ + tmp = g_strdup (", org.wfa.wfd1.0"); + g_strlcat (str, tmp, strlen (tmp) + strlen (str) + 1); + + gst_rtsp_message_init_response (ctx->response, GST_RTSP_STS_OK, + gst_rtsp_status_as_text (GST_RTSP_STS_OK), ctx->request); + + gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_PUBLIC, str); + g_free (str); + str = NULL; + + res = + gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_USER_AGENT, + &user_agent, 0); + if (res == GST_RTSP_OK) { + gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_USER_AGENT, + user_agent); + } else { + return FALSE; + } + + res = gst_rtsp_client_send_message (client, NULL, ctx->response); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res); + return FALSE; + } + + GST_DEBUG_OBJECT (client, "Sent M2 response..."); + + g_signal_emit (_client, + gst_rtsp_client_wfd_signals[SIGNAL_WFD_OPTIONS_REQUEST], 0, ctx); + + return TRUE; +} + +static gboolean +handle_wfd_get_param_request (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPResult res = GST_RTSP_OK; + guint8 *data = NULL; + guint size = 0; + + GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client); + + /* parsing the GET_PARAMTER request */ + res = gst_rtsp_message_get_body (ctx->request, (guint8 **) & data, &size); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (_client, "Failed to get body of request..."); + return FALSE; + } + + if (size == 0) { + send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx); + } else { + /* TODO-WFD: Handle other GET_PARAMETER request from sink */ + } + + return TRUE; +} + +static gboolean +handle_wfd_set_param_request (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPResult res = GST_RTSP_OK; + guint8 *data = NULL; + guint size = 0; + + GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client); + + res = gst_rtsp_message_get_body (ctx->request, &data, &size); + if (res != GST_RTSP_OK) + goto bad_request; + + if (size == 0) { + /* no body, keep-alive request */ + send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx); + } else { + if (data != NULL) { + GST_INFO_OBJECT (_client, "SET_PARAMETER Request : %s(%d)", data, size); + if (g_strcmp0 ((const gchar *) data, "wfd_idr_request")) + send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx); +#if 0 + else + /* TODO-WFD : Handle other set param request */ + send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx); +#endif + } else { + goto bad_request; + } + } + + return TRUE; + + /* ERRORS */ +bad_request: + { + GST_ERROR ("_client %p: bad request", _client); + send_generic_wfd_response (_client, GST_RTSP_STS_BAD_REQUEST, ctx); + return FALSE; + } +} + +#if 0 +static gboolean +gst_rtsp_wfd_client_parse_methods (GstRTSPWFDClient * client, + GstRTSPMessage * response) +{ + GstRTSPHeaderField field; + gchar *respoptions; + gchar **options; + gint indx = 0; + gint i; + gboolean found_wfd_method = FALSE; + + /* reset supported methods */ + client->supported_methods = 0; + + /* Try Allow Header first */ + field = GST_RTSP_HDR_ALLOW; + while (TRUE) { + respoptions = NULL; + gst_rtsp_message_get_header (response, field, &respoptions, indx); + if (indx == 0 && !respoptions) { + /* if no Allow header was found then try the Public header... */ + field = GST_RTSP_HDR_PUBLIC; + gst_rtsp_message_get_header (response, field, &respoptions, indx); + } + if (!respoptions) + break; + + /* If we get here, the server gave a list of supported methods, parse + * them here. The string is like: + * + * OPTIONS, PLAY, SETUP, ... + */ + options = g_strsplit (respoptions, ",", 0); + + for (i = 0; options[i]; i++) { + gchar *stripped; + gint method; + + stripped = g_strstrip (options[i]); + method = gst_rtsp_find_method (stripped); + + if (!g_ascii_strcasecmp ("org.wfa.wfd1.0", stripped)) + found_wfd_method = TRUE; + + /* keep bitfield of supported methods */ + if (method != GST_RTSP_INVALID) + client->supported_methods |= method; + } + g_strfreev (options); + + indx++; + } + + if (!found_wfd_method) { + GST_ERROR_OBJECT (client, + "WFD client is not supporting WFD mandatory message : org.wfa.wfd1.0..."); + goto no_required_methods; + } + + /* Checking mandatory method */ + if (!(client->supported_methods & GST_RTSP_SET_PARAMETER)) { + GST_ERROR_OBJECT (client, + "WFD client is not supporting WFD mandatory message : SET_PARAMETER..."); + goto no_required_methods; + } + + /* Checking mandatory method */ + if (!(client->supported_methods & GST_RTSP_GET_PARAMETER)) { + GST_ERROR_OBJECT (client, + "WFD client is not supporting WFD mandatory message : GET_PARAMETER..."); + goto no_required_methods; + } + + if (!(client->supported_methods & GST_RTSP_OPTIONS)) { + GST_INFO_OBJECT (client, "assuming OPTIONS is supported by client..."); + client->supported_methods |= GST_RTSP_OPTIONS; + } + + return TRUE; + +/* ERRORS */ +no_required_methods: + { + GST_ELEMENT_ERROR (client, RESOURCE, OPEN_READ, (NULL), + ("WFD Client does not support mandatory methods.")); + return FALSE; + } +} +#endif + +typedef enum +{ + M1_REQ_MSG, + M1_RES_MSG, + M2_REQ_MSG, + M2_RES_MSG, + M3_REQ_MSG, + M3_RES_MSG, + M4_REQ_MSG, + M4_RES_MSG, + M5_REQ_MSG, + TEARDOWN_TRIGGER, + PLAY_TRIGGER, + PAUSE_TRIGGER, +} GstWFDMessageType; + +static gboolean +_set_negotiated_audio_codec (GstRTSPWFDClient *client, + guint audio_codec) +{ + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + + GstRTSPMediaFactory *factory = NULL; + GstRTSPMountPoints *mount_points = NULL; + gchar *path = NULL; + gint matched = 0; + gboolean ret = TRUE; + + if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) { + ret = FALSE; + GST_ERROR_OBJECT (client, "Failed to set negotiated audio codec: no mount points..."); + goto no_mount_points; + } + + path = g_strdup(WFD_MOUNT_POINT); + if (!path) { + ret = FALSE; + GST_ERROR_OBJECT (client, "Failed to set negotiated audio codec: no path..."); + goto no_path; + } + + if (!(factory = gst_rtsp_mount_points_match (mount_points, + path, &matched))) { + GST_ERROR_OBJECT (client, "Failed to set negotiated audio codec: no factory..."); + ret = FALSE; + goto no_factory; + } + + gst_rtsp_media_factory_wfd_set_audio_codec (factory, + audio_codec); + ret = TRUE; + + g_object_unref(factory); + +no_factory: + g_free(path); +no_path: + g_object_unref(mount_points); +no_mount_points: + return ret; +} + +static gboolean +_set_negotiated_resolution(GstRTSPWFDClient *client, + guint32 width, guint32 height) +{ + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + + GstRTSPMediaFactory *factory = NULL; + GstRTSPMountPoints *mount_points = NULL; + gchar *path = NULL; + gint matched = 0; + gboolean ret = TRUE; + + if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) { + ret = FALSE; + GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no mount points..."); + goto no_mount_points; + } + + path = g_strdup(WFD_MOUNT_POINT); + if (!path) { + ret = FALSE; + GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no path..."); + goto no_path; + } + + if (!(factory = gst_rtsp_mount_points_match (mount_points, + path, &matched))) { + GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no factory..."); + ret = FALSE; + goto no_factory; + } + + gst_rtsp_media_factory_wfd_set_negotiated_resolution(factory, + width, height); + ret = TRUE; + + g_object_unref(factory); + +no_factory: + g_free(path); +no_path: + g_object_unref(mount_points); +no_mount_points: + return ret; +} + +static void +_set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, + gchar ** data, guint * len) +{ + GString *buf = NULL; + GstWFDMessage *msg = NULL; + GstWFDResult wfd_res = GST_WFD_EINVAL; + GstRTSPWFDClientPrivate *priv = NULL; + priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + g_return_if_fail (priv != NULL); + + buf = g_string_new (""); + g_return_if_fail (buf != NULL); + + if (msg_type == M3_REQ_MSG) { + /* create M3 request to be sent */ + wfd_res = gst_wfd_message_new (&msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to create wfd message..."); + goto error; + } + + wfd_res = gst_wfd_message_init (msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to init wfd message..."); + goto error; + } + + /* set the supported audio formats by the WFD server */ + wfd_res = + gst_wfd_message_set_supported_audio_format (msg, GST_WFD_AUDIO_UNKNOWN, + GST_WFD_FREQ_UNKNOWN, GST_WFD_CHANNEL_UNKNOWN, 0, 0); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set supported audio formats on wfd message..."); + goto error; + } + + /* set the supported Video formats by the WFD server */ + wfd_res = + gst_wfd_message_set_supported_video_format (msg, GST_WFD_VIDEO_UNKNOWN, + GST_WFD_VIDEO_CEA_RESOLUTION, GST_WFD_CEA_UNKNOWN, GST_WFD_CEA_UNKNOWN, + GST_WFD_VESA_UNKNOWN, GST_WFD_HH_UNKNOWN, GST_WFD_H264_UNKNOWN_PROFILE, + GST_WFD_H264_LEVEL_UNKNOWN, 0, 0, 0, 0, 0, 0); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set supported video formats on wfd message..."); + goto error; + } + + wfd_res = gst_wfd_message_set_display_edid (msg, 0, 0, NULL); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set display edid type on wfd message..."); + goto error; + } + + if (priv->protection_enabled) { + wfd_res = + gst_wfd_message_set_contentprotection_type (msg, GST_WFD_HDCP_NONE, + 0); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set supported content protection type on wfd message..."); + goto error; + } + } + + /* set the preffered RTP ports for the WFD server */ + wfd_res = + gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_UNKNOWN, + GST_WFD_RTSP_PROFILE_UNKNOWN, GST_WFD_RTSP_LOWER_TRANS_UNKNOWN, 0, 0); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set supported video formats on wfd message..."); + goto error; + } + + *data = gst_wfd_message_param_names_as_text (msg); + if (*data == NULL) { + GST_ERROR_OBJECT (client, "Failed to get wfd message as text..."); + goto error; + } else { + *len = strlen (*data); + } + } else if (msg_type == M4_REQ_MSG) { + GstRTSPUrl *url = NULL; + + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + GstRTSPConnection *connection = + gst_rtsp_client_get_connection (parent_client); + + /* Parameters for the preffered audio formats */ + GstWFDAudioFormats taudiocodec = GST_WFD_AUDIO_UNKNOWN; + GstWFDAudioFreq taudiofreq = GST_WFD_FREQ_UNKNOWN; + GstWFDAudioChannels taudiochannels = GST_WFD_CHANNEL_UNKNOWN; + + /* Parameters for the preffered video formats */ + GstWFDVideoCEAResolution tcCEAResolution = GST_WFD_CEA_UNKNOWN; + GstWFDVideoVESAResolution tcVESAResolution = GST_WFD_VESA_UNKNOWN; + GstWFDVideoHHResolution tcHHResolution = GST_WFD_HH_UNKNOWN; + GstWFDVideoH264Profile tcProfile; + GstWFDVideoH264Level tcLevel; + guint64 resolution_supported = 0; + + url = gst_rtsp_connection_get_url (connection); + if (url == NULL) { + GST_ERROR_OBJECT (client, "Failed to get connection URL"); + return; + } + + /* Logic to negotiate with information of M3 response */ + /* create M4 request to be sent */ + wfd_res = gst_wfd_message_new (&msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to create wfd message..."); + goto error; + } + + wfd_res = gst_wfd_message_init (msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to init wfd message..."); + goto error; + } + + g_string_append_printf (buf, "rtsp://"); + + if (priv->host_address) { + g_string_append (buf, priv->host_address); + } else { + GST_ERROR_OBJECT (client, "Failed to get host address"); + if (buf) g_string_free (buf, TRUE); + goto error; + } + + g_string_append_printf (buf, "/wfd1.0/streamid=0"); + wfd_res = + gst_wfd_message_set_presentation_url (msg, g_string_free (buf, FALSE), + NULL); + + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to set presentation url"); + goto error; + } + + taudiocodec = wfd_get_prefered_audio_codec (priv->audio_codec, priv->caCodec); + priv->caCodec = taudiocodec; + if (!_set_negotiated_audio_codec(client, priv->caCodec)) { + GST_ERROR_OBJECT (client, "Failed to set negotiated " + "audio codec to media factory..."); + } + + if (priv->cFreq & GST_WFD_FREQ_48000) + taudiofreq = GST_WFD_FREQ_48000; + else if (priv->cFreq & GST_WFD_FREQ_44100) + taudiofreq = GST_WFD_FREQ_44100; + priv->cFreq = taudiofreq; + + /* TODO-WFD: Currently only 2 channels is present */ + if (priv->cChanels & GST_WFD_CHANNEL_8) + taudiochannels = GST_WFD_CHANNEL_2; + else if (priv->cChanels & GST_WFD_CHANNEL_6) + taudiochannels = GST_WFD_CHANNEL_2; + else if (priv->cChanels & GST_WFD_CHANNEL_4) + taudiochannels = GST_WFD_CHANNEL_2; + else if (priv->cChanels & GST_WFD_CHANNEL_2) + taudiochannels = GST_WFD_CHANNEL_2; + priv->cChanels = taudiochannels; + + wfd_res = + gst_wfd_message_set_prefered_audio_format (msg, taudiocodec, taudiofreq, + taudiochannels, priv->cBitwidth, priv->caLatency); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (priv, "Failed to set preffered audio formats..."); + goto error; + } + + /* Set the preffered video formats */ + priv->cvCodec = GST_WFD_VIDEO_H264; + priv->cProfile = tcProfile = GST_WFD_H264_BASE_PROFILE; + priv->cLevel = tcLevel = GST_WFD_H264_LEVEL_3_1; + + resolution_supported = priv->video_resolution_supported; + + /* TODO-WFD: Need to verify this logic + if(priv->edid_supported) { + if (priv->edid_hres < 1920) resolution_supported = resolution_supported & 0x8C7F; + if (priv->edid_hres < 1280) resolution_supported = resolution_supported & 0x1F; + if (priv->edid_hres < 720) resolution_supported = resolution_supported & 0x01; + } + */ + + if (priv->video_native_resolution == GST_WFD_VIDEO_CEA_RESOLUTION) { + tcCEAResolution = + wfd_get_prefered_resolution (resolution_supported, + priv->cCEAResolution, priv->video_native_resolution, &priv->cMaxWidth, + &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved); + GST_DEBUG + ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d", + tcCEAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate, + priv->cInterleaved); + } else if (priv->video_native_resolution == GST_WFD_VIDEO_VESA_RESOLUTION) { + tcVESAResolution = + wfd_get_prefered_resolution (resolution_supported, + priv->cVESAResolution, priv->video_native_resolution, + &priv->cMaxWidth, &priv->cMaxHeight, &priv->cFramerate, + &priv->cInterleaved); + GST_DEBUG + ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d", + tcVESAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate, + priv->cInterleaved); + } else if (priv->video_native_resolution == GST_WFD_VIDEO_HH_RESOLUTION) { + tcHHResolution = + wfd_get_prefered_resolution (resolution_supported, + priv->cHHResolution, priv->video_native_resolution, &priv->cMaxWidth, + &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved); + GST_DEBUG + ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d", + tcHHResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate, + priv->cInterleaved); + } + + if (!_set_negotiated_resolution(client, priv->cMaxWidth, + priv->cMaxHeight)) { + GST_ERROR_OBJECT (client, "Failed to set negotiated " + "resolution to media factory..."); + } + + wfd_res = + gst_wfd_message_set_prefered_video_format (msg, priv->cvCodec, + priv->video_native_resolution, GST_WFD_CEA_UNKNOWN, tcCEAResolution, + tcVESAResolution, tcHHResolution, tcProfile, tcLevel, priv->cvLatency, + priv->cMaxWidth, priv->cMaxHeight, priv->cmin_slice_size, + priv->cslice_enc_params, priv->cframe_rate_control); + + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to set preffered video formats..."); + goto error; + } + + /* set the preffered RTP ports for the WFD server */ + wfd_res = + gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_RTP, + GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, priv->crtp_port0, priv->crtp_port1); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set supported video formats on wfd message..."); + goto error; + } + + *data = gst_wfd_message_as_text (msg); + if (*data == NULL) { + GST_ERROR_OBJECT (client, "Failed to get wfd message as text..."); + goto error; + } else { + *len = strlen (*data); + } + } else if (msg_type == M5_REQ_MSG) { + g_string_append (buf, "wfd_trigger_method: SETUP"); + g_string_append (buf, "\r\n"); + *len = buf->len; + *data = g_string_free (buf, FALSE); + } else if (msg_type == TEARDOWN_TRIGGER) { + g_string_append (buf, "wfd_trigger_method: TEARDOWN"); + g_string_append (buf, "\r\n"); + *len = buf->len; + *data = g_string_free (buf, FALSE); + } else if (msg_type == PLAY_TRIGGER) { + g_string_append (buf, "wfd_trigger_method: PLAY"); + g_string_append (buf, "\r\n"); + *len = buf->len; + *data = g_string_free (buf, FALSE); + } else if (msg_type == PAUSE_TRIGGER) { + g_string_append (buf, "wfd_trigger_method: PAUSE"); + g_string_append (buf, "\r\n"); + *len = buf->len; + *data = g_string_free (buf, FALSE); + } else { + return; + } + + return; + +error: + *data = NULL; + *len = 0; + + return; +} + +/** +* prepare_request: +* @client: client object +* @request : requst message to be prepared +* @method : RTSP method of the request +* @url : url need to be in the request +* @message_type : WFD message type +* @trigger_type : trigger method to be used for M5 mainly +* +* Prepares request based on @method & @message_type +* +* Returns: a #GstRTSPResult. +*/ +GstRTSPResult +prepare_request (GstRTSPWFDClient * client, GstRTSPMessage * request, + GstRTSPMethod method, gchar * url) +{ + GstRTSPResult res = GST_RTSP_OK; + gchar *str = NULL; + + if (method == GST_RTSP_GET_PARAMETER || method == GST_RTSP_SET_PARAMETER) { + g_free (url); + url = g_strdup ("rtsp://localhost/wfd1.0"); + } + + GST_DEBUG_OBJECT (client, "Preparing request: %d", method); + + /* initialize the request */ + res = gst_rtsp_message_init_request (request, method, url); + if (res < 0) { + GST_ERROR ("init request failed"); + return res; + } + + switch (method) { + /* Prepare OPTIONS request to send */ + case GST_RTSP_OPTIONS:{ + /* add wfd specific require filed "org.wfa.wfd1.0" */ + str = g_strdup ("org.wfa.wfd1.0"); + res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_REQUIRE, str); + if (res < 0) { + GST_ERROR ("Failed to add header"); + g_free (str); + return res; + } + + g_free (str); + break; + } + + /* Prepare GET_PARAMETER request */ + case GST_RTSP_GET_PARAMETER:{ + gchar *msg = NULL; + guint msglen = 0; + GString *msglength; + + /* add content type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE, + "text/parameters"); + if (res < 0) { + GST_ERROR ("Failed to add header"); + return res; + } + + _set_wfd_message_body (client, M3_REQ_MSG, &msg, &msglen); + msglength = g_string_new (""); + g_string_append_printf (msglength, "%d", msglen); + GST_DEBUG ("M3 server side message body: %s", msg); + + /* add content-length type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, + g_string_free (msglength, FALSE)); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + g_free (msg); + break; + } + + /* Prepare SET_PARAMETER request */ + case GST_RTSP_SET_PARAMETER:{ + gchar *msg = NULL; + guint msglen = 0; + GString *msglength; + + /* add content type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE, + "text/parameters"); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp request..."); + goto error; + } + + _set_wfd_message_body (client, M4_REQ_MSG, &msg, &msglen); + msglength = g_string_new (""); + g_string_append_printf (msglength, "%d", msglen); + GST_DEBUG ("M4 server side message body: %s", msg); + + /* add content-length type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, + g_string_free (msglength, FALSE)); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + g_free (msg); + break; + } + + default:{ + } + } + + return res; + +error: + return GST_RTSP_ERROR; +} + +GstRTSPResult +prepare_trigger_request (GstRTSPWFDClient * client, GstRTSPMessage * request, + GstWFDTriggerType trigger_type, gchar * url) +{ + GstRTSPResult res = GST_RTSP_OK; + + /* initialize the request */ + res = gst_rtsp_message_init_request (request, GST_RTSP_SET_PARAMETER, url); + if (res < 0) { + GST_ERROR ("init request failed"); + return res; + } + + switch (trigger_type) { + case WFD_TRIGGER_SETUP:{ + gchar *msg; + guint msglen = 0; + GString *msglength; + + /* add content type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE, + "text/parameters"); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp request..."); + goto error; + } + + _set_wfd_message_body (client, M5_REQ_MSG, &msg, &msglen); + msglength = g_string_new (""); + g_string_append_printf (msglength, "%d", msglen); + GST_DEBUG ("M5 server side message body: %s", msg); + + /* add content-length type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, + g_string_free (msglength, FALSE)); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + g_free (msg); + break; + } + case WFD_TRIGGER_TEARDOWN:{ + gchar *msg; + guint msglen = 0; + GString *msglength; + + /* add content type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE, + "text/parameters"); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp request..."); + goto error; + } + + _set_wfd_message_body (client, TEARDOWN_TRIGGER, &msg, &msglen); + msglength = g_string_new (""); + g_string_append_printf (msglength, "%d", msglen); + GST_DEBUG ("Trigger TEARDOWN server side message body: %s", msg); + + /* add content-length type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, + g_string_free (msglength, FALSE)); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + g_free (msg); + break; + } + case WFD_TRIGGER_PLAY:{ + gchar *msg; + guint msglen = 0; + GString *msglength; + + /* add content type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE, + "text/parameters"); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp request..."); + goto error; + } + + _set_wfd_message_body (client, PLAY_TRIGGER, &msg, &msglen); + msglength = g_string_new (""); + g_string_append_printf (msglength, "%d", msglen); + GST_DEBUG ("Trigger PLAY server side message body: %s", msg); + + /* add content-length type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, + g_string_free (msglength, FALSE)); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + g_free (msg); + break; + } + case WFD_TRIGGER_PAUSE:{ + gchar *msg; + guint msglen = 0; + GString *msglength; + + /* add content type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE, + "text/parameters"); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp request..."); + goto error; + } + + _set_wfd_message_body (client, PAUSE_TRIGGER, &msg, &msglen); + msglength = g_string_new (""); + g_string_append_printf (msglength, "%d", msglen); + GST_DEBUG ("Trigger PAUSE server side message body: %s", msg); + + /* add content-length type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, + g_string_free (msglength, FALSE)); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + g_free (msg); + break; + } + /* TODO-WFD: implement to handle other trigger type */ + default:{ + } + } + + return res; + +error: + return res; +} + + +void +send_request (GstRTSPWFDClient * client, GstRTSPSession * session, + GstRTSPMessage * request) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + + /* remove any previous header */ + gst_rtsp_message_remove_header (request, GST_RTSP_HDR_SESSION, -1); + + /* add the new session header for new session ids */ + if (session) { + guint timeout; + const gchar *sessionid = NULL; + gchar *str; + + sessionid = gst_rtsp_session_get_sessionid (session); + GST_INFO_OBJECT (client, "Session id : %s", sessionid); + + timeout = gst_rtsp_session_get_timeout (session); + if (timeout != DEFAULT_WFD_TIMEOUT) + str = g_strdup_printf ("%s; timeout=%d", sessionid, timeout); + else + str = g_strdup (sessionid); + + gst_rtsp_message_take_header (request, GST_RTSP_HDR_SESSION, str); + } +#if 0 + if (gst_debug_category_get_threshold (rtsp_wfd_client_debug) >= GST_LEVEL_LOG) { + gst_rtsp_message_dump (request); + } +#endif + res = gst_rtsp_client_send_message (parent_client, session, request); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res); + } + + gst_rtsp_message_unset (request); +} + +/** +* prepare_response: +* @client: client object +* @request : requst message received +* @response : response to be prepare based on request +* @method : RTSP method +* +* prepare response to the request based on @method & @message_type +* +* Returns: a #GstRTSPResult. +*/ +GstRTSPResult +prepare_response (GstRTSPWFDClient * client, GstRTSPMessage * request, + GstRTSPMessage * response, GstRTSPMethod method) +{ + GstRTSPResult res = GST_RTSP_OK; + + switch (method) { + /* prepare OPTIONS response */ + case GST_RTSP_OPTIONS:{ + GstRTSPMethod options; + gchar *tmp = NULL; + gchar *str = NULL; + gchar *user_agent = NULL; + + options = GST_RTSP_OPTIONS | + GST_RTSP_PAUSE | + GST_RTSP_PLAY | + GST_RTSP_SETUP | + GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN; + + str = gst_rtsp_options_as_text (options); + + /*append WFD specific method */ + tmp = g_strdup (", org.wfa.wfd1.0"); + g_strlcat (str, tmp, strlen (tmp) + strlen (str) + 1); + + gst_rtsp_message_init_response (response, GST_RTSP_STS_OK, + gst_rtsp_status_as_text (GST_RTSP_STS_OK), request); + + gst_rtsp_message_add_header (response, GST_RTSP_HDR_PUBLIC, str); + g_free (str); + str = NULL; + res = + gst_rtsp_message_get_header (request, GST_RTSP_HDR_USER_AGENT, + &user_agent, 0); + if (res == GST_RTSP_OK) { + gst_rtsp_message_add_header (response, GST_RTSP_HDR_USER_AGENT, + user_agent); + } else + res = GST_RTSP_OK; + break; + } + default: + GST_ERROR_OBJECT (client, "Unhandled method..."); + return GST_RTSP_EINVAL; + break; + } + + return res; +} + +static void +send_generic_wfd_response (GstRTSPWFDClient * client, GstRTSPStatusCode code, + GstRTSPContext * ctx) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + + gst_rtsp_message_init_response (ctx->response, code, + gst_rtsp_status_as_text (code), ctx->request); + + res = gst_rtsp_client_send_message (parent_client, NULL, ctx->response); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res); + } +} + + +static GstRTSPResult +handle_M1_message (GstRTSPWFDClient * client) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPMessage request = { 0 }; + + res = prepare_request (client, &request, GST_RTSP_OPTIONS, (gchar *) "*"); + if (GST_RTSP_OK != res) { + GST_ERROR_OBJECT (client, "Failed to prepare M1 request....\n"); + return res; + } + + GST_DEBUG_OBJECT (client, "Sending M1 request.. (OPTIONS request)"); + + send_request (client, NULL, &request); + + return res; +} + +/** +* handle_M3_message: +* @client: client object +* +* Handles M3 WFD message. +* This API will send M3 message (GET_PARAMETER) to WFDSink to query supported formats by the WFDSink. +* After getting supported formats info, this API will set those values on WFDConfigMessage obj +* +* Returns: a #GstRTSPResult. +*/ +static GstRTSPResult +handle_M3_message (GstRTSPWFDClient * client) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPMessage request = { 0 }; + GstRTSPUrl *url = NULL; + gchar *url_str = NULL; + + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + GstRTSPConnection *connection = + gst_rtsp_client_get_connection (parent_client); + + url = gst_rtsp_connection_get_url (connection); + if (url == NULL) { + GST_ERROR_OBJECT (client, "Failed to get connection URL"); + res = GST_RTSP_ERROR; + goto error; + } + + url_str = gst_rtsp_url_get_request_uri (url); + if (url_str == NULL) { + GST_ERROR_OBJECT (client, "Failed to get connection URL"); + res = GST_RTSP_ERROR; + goto error; + } + + res = prepare_request (client, &request, GST_RTSP_GET_PARAMETER, url_str); + if (GST_RTSP_OK != res) { + GST_ERROR_OBJECT (client, "Failed to prepare M3 request....\n"); + goto error; + } + + GST_DEBUG_OBJECT (client, "Sending GET_PARAMETER request message (M3)..."); + + send_request (client, NULL, &request); + + return res; + +error: + return res; +} + +static GstRTSPResult +handle_M4_message (GstRTSPWFDClient * client) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPMessage request = { 0 }; + GstRTSPUrl *url = NULL; + gchar *url_str = NULL; + + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + GstRTSPConnection *connection = + gst_rtsp_client_get_connection (parent_client); + + url = gst_rtsp_connection_get_url (connection); + if (url == NULL) { + GST_ERROR_OBJECT (client, "Failed to get connection URL"); + res = GST_RTSP_ERROR; + goto error; + } + + url_str = gst_rtsp_url_get_request_uri (url); + if (url_str == NULL) { + GST_ERROR_OBJECT (client, "Failed to get connection URL"); + res = GST_RTSP_ERROR; + goto error; + } + + res = prepare_request (client, &request, GST_RTSP_SET_PARAMETER, url_str); + if (GST_RTSP_OK != res) { + GST_ERROR_OBJECT (client, "Failed to prepare M4 request....\n"); + goto error; + } + + GST_DEBUG_OBJECT (client, "Sending SET_PARAMETER request message (M4)..."); + + send_request (client, NULL, &request); + + return res; + +error: + return res; +} + +GstRTSPResult +gst_rtsp_wfd_client_trigger_request (GstRTSPWFDClient * client, + GstWFDTriggerType type) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPMessage request = { 0 }; + GstRTSPUrl *url = NULL; + gchar *url_str = NULL; + + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + GstRTSPConnection *connection = + gst_rtsp_client_get_connection (parent_client); + + url = gst_rtsp_connection_get_url (connection); + if (url == NULL) { + GST_ERROR_OBJECT (client, "Failed to get connection URL"); + res = GST_RTSP_ERROR; + goto error; + } + + url_str = gst_rtsp_url_get_request_uri (url); + if (url_str == NULL) { + GST_ERROR_OBJECT (client, "Failed to get connection URL"); + res = GST_RTSP_ERROR; + goto error; + } + + res = prepare_trigger_request (client, &request, type, url_str); + if (GST_RTSP_OK != res) { + GST_ERROR_OBJECT (client, "Failed to prepare M5 request....\n"); + goto error; + } + + GST_DEBUG_OBJECT (client, "Sending trigger request message...: %d", type); + + send_request (client, NULL, &request); + + return res; + +error: + return res; +} + +GstRTSPResult +gst_rtsp_wfd_client_set_video_supported_resolution (GstRTSPWFDClient * client, + guint64 supported_reso) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL); + + priv->video_resolution_supported = supported_reso; + GST_DEBUG ("Resolution : %"G_GUINT64_FORMAT, supported_reso); + + return res; +} + +GstRTSPResult +gst_rtsp_wfd_client_set_video_native_resolution (GstRTSPWFDClient * client, + guint64 native_reso) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL); + + priv->video_native_resolution = native_reso; + GST_DEBUG ("Native Resolution : %"G_GUINT64_FORMAT, native_reso); + + return res; +} + +GstRTSPResult +gst_rtsp_wfd_client_set_audio_codec (GstRTSPWFDClient * client, + guint8 audio_codec) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL); + + priv->audio_codec = audio_codec; + GST_DEBUG ("Audio codec : %d", audio_codec); + + return res; +} + +static gboolean +wfd_ckeck_keep_alive_response (gpointer userdata) +{ + GstRTSPWFDClient *client = (GstRTSPWFDClient *)userdata; + GstRTSPWFDClientPrivate *priv = NULL; + if (!client) { + return FALSE; + } + + priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL); + + if (priv->keep_alive_flag) { + return FALSE; + } + else { + GST_INFO ("%p: source error notification", client); + // FIXME Do something here. Maybe emit some signal? + return FALSE; + } +} + +/*Sending keep_alive (M16) message. + Without calling prepare_request function.*/ +static GstRTSPResult +handle_M16_message (GstRTSPWFDClient * client) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPMessage request = { 0 }; + gchar *url_str = NULL; + + url_str = g_strdup("rtsp://localhost/wfd1.0"); + + res = gst_rtsp_message_init_request (&request, GST_RTSP_GET_PARAMETER, url_str); + if (res < 0) { + GST_ERROR ("init request failed"); + return FALSE; + } + + send_request (client, NULL, &request); + return GST_RTSP_OK; +} + +/*CHecking whether source has got response of any request. + * If yes, keep alive message is sent otherwise error message + * will be displayed.*/ +static gboolean +keep_alive_condition(gpointer userdata) +{ + GstRTSPWFDClient *client; + GstRTSPWFDClientPrivate *priv; + GstRTSPResult res; + client = (GstRTSPWFDClient *)userdata; + if (!client) { + return FALSE; + } + priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + g_return_val_if_fail (priv != NULL, FALSE); + + g_mutex_lock(&priv->keep_alive_lock); + if(!priv->keep_alive_flag) { + g_timeout_add(5000, wfd_ckeck_keep_alive_response, client); + } + else { + GST_DEBUG_OBJECT (client, "have received last keep alive message response"); + } + + GST_DEBUG("sending keep alive message"); + res = handle_M16_message(client); + if(res == GST_RTSP_OK) { + priv->keep_alive_flag = FALSE; + } else { + GST_ERROR_OBJECT (client, "Failed to send Keep Alive Message"); + g_mutex_unlock(&priv->keep_alive_lock); + return FALSE; + } + + g_mutex_unlock(&priv->keep_alive_lock); + return TRUE; +} + +static +void wfd_set_keep_alive_condition(GstRTSPWFDClient * client) +{ + g_timeout_add((DEFAULT_WFD_TIMEOUT-5)*1000, keep_alive_condition, client); +} + +void +gst_rtsp_wfd_client_set_host_address (GstRTSPWFDClient *client, const gchar * address) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + g_return_if_fail (priv != NULL); + + if (priv->host_address) { + g_free (priv->host_address); + } + + priv->host_address = g_strdup (address); +} + +guint +gst_rtsp_wfd_client_get_audio_codec(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->caCodec; +} + +guint +gst_rtsp_wfd_client_get_audio_freq(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cFreq; +} + +guint +gst_rtsp_wfd_client_get_audio_channels(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cChanels; +} + +guint +gst_rtsp_wfd_client_get_audio_bit_width(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cBitwidth; +} + +guint +gst_rtsp_wfd_client_get_audio_latency(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->caLatency; +} + +guint +gst_rtsp_wfd_client_get_video_codec(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cvCodec; +} + +guint +gst_rtsp_wfd_client_get_video_native(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cNative; +} + +guint64 +gst_rtsp_wfd_client_get_video_native_resolution(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cNativeResolution; +} + +guint +gst_rtsp_wfd_client_get_video_cea_resolution(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cCEAResolution; +} + +guint +gst_rtsp_wfd_client_get_video_vesa_resolution(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cVESAResolution; +} + +guint +gst_rtsp_wfd_client_get_video_hh_resolution(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cHHResolution; +} + +guint +gst_rtsp_wfd_client_get_video_profile(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cProfile; +} + +guint +gst_rtsp_wfd_client_get_video_level(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cLevel; +} + +guint +gst_rtsp_wfd_client_get_video_latency(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cvLatency; +} + +guint32 +gst_rtsp_wfd_client_get_video_max_height(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cMaxHeight; +} + +guint32 +gst_rtsp_wfd_client_get_video_max_width(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cMaxWidth; +} + +guint32 +gst_rtsp_wfd_client_get_video_framerate(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cFramerate; +} + +guint32 +gst_rtsp_wfd_client_get_video_min_slice_size(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cmin_slice_size; +} + +guint32 +gst_rtsp_wfd_client_get_video_slice_enc_params(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cslice_enc_params; +} + +guint +gst_rtsp_wfd_client_get_video_framerate_control(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->cframe_rate_control; +} + +guint32 +gst_rtsp_wfd_client_get_rtp_port0(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->crtp_port0; +} + +guint32 +gst_rtsp_wfd_client_get_rtp_port1(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->crtp_port1; +} + +gboolean +gst_rtsp_wfd_client_get_edid_supported(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->edid_supported; +} + +guint32 +gst_rtsp_wfd_client_get_edid_hresolution(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->edid_hres; +} + +guint32 +gst_rtsp_wfd_client_get_edid_vresolution(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->edid_vres; +} + +gboolean +gst_rtsp_wfd_client_get_protection_enabled(GstRTSPWFDClient *client) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + return priv->protection_enabled; +} + +void +gst_rtsp_wfd_client_set_audio_freq(GstRTSPWFDClient *client, guint freq) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + priv->cFreq = freq; +} + +void +gst_rtsp_wfd_client_set_edid_supported(GstRTSPWFDClient *client, gboolean supported) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + priv->edid_supported = supported; +} + +void +gst_rtsp_wfd_client_set_edid_hresolution(GstRTSPWFDClient *client, guint32 reso) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + priv->edid_hres = reso; +} + +void +gst_rtsp_wfd_client_set_edid_vresolution(GstRTSPWFDClient *client, guint32 reso) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + priv->edid_vres = reso; +} + +void +gst_rtsp_wfd_client_set_protection_enabled(GstRTSPWFDClient *client, gboolean enable) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + priv->protection_enabled = enable; +} + +void gst_rtsp_wfd_client_set_keep_alive_flag(GstRTSPWFDClient *client, gboolean flag) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, 0); + + g_mutex_lock(&priv->keep_alive_lock); + if (priv->keep_alive_flag == !(flag)) + priv->keep_alive_flag = flag; + g_mutex_unlock(&priv->keep_alive_lock); +} + +void +gst_rtsp_wfd_client_set_aud_codec (GstRTSPWFDClient *client, guint acodec) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->caCodec = acodec; +} + +void +gst_rtsp_wfd_client_set_audio_channels(GstRTSPWFDClient *client, guint channels) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cChanels = channels; +} + +void +gst_rtsp_wfd_client_set_audio_bit_width(GstRTSPWFDClient *client, guint bwidth) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cBitwidth = bwidth; +} + +void +gst_rtsp_wfd_client_set_audio_latency(GstRTSPWFDClient *client, guint latency) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->caLatency = latency; +} + +void +gst_rtsp_wfd_client_set_video_codec(GstRTSPWFDClient *client, guint vcodec) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cvCodec = vcodec; +} + +void +gst_rtsp_wfd_client_set_video_native(GstRTSPWFDClient *client, guint native) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cNative = native; +} + +void +gst_rtsp_wfd_client_set_vid_native_resolution(GstRTSPWFDClient *client, guint64 res) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cNativeResolution = res; +} + +void +gst_rtsp_wfd_client_set_video_cea_resolution(GstRTSPWFDClient *client, guint res) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cCEAResolution = res; +} + +void +gst_rtsp_wfd_client_set_video_vesa_resolution(GstRTSPWFDClient *client, guint res) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cVESAResolution = res; +} + +void +gst_rtsp_wfd_client_set_video_hh_resolution(GstRTSPWFDClient *client, guint res) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cHHResolution = res; +} + +void +gst_rtsp_wfd_client_set_video_profile(GstRTSPWFDClient *client, guint profile) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cProfile = profile; +} + +void +gst_rtsp_wfd_client_set_video_level(GstRTSPWFDClient *client, guint level) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cLevel = level; +} + +void +gst_rtsp_wfd_client_set_video_latency(GstRTSPWFDClient *client, guint latency) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cvLatency = latency; +} + +void +gst_rtsp_wfd_client_set_video_max_height(GstRTSPWFDClient *client, guint32 height) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cMaxHeight = height; +} + +void +gst_rtsp_wfd_client_set_video_max_width(GstRTSPWFDClient *client, guint32 width) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cMaxWidth = width; +} + +void +gst_rtsp_wfd_client_set_video_framerate(GstRTSPWFDClient *client, guint32 framerate) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cFramerate = framerate; +} + +void +gst_rtsp_wfd_client_set_video_min_slice_size(GstRTSPWFDClient *client, guint32 slice_size) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cmin_slice_size = slice_size; +} + +void +gst_rtsp_wfd_client_set_video_slice_enc_params(GstRTSPWFDClient *client, guint32 enc_params) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cslice_enc_params = enc_params; +} + +void +gst_rtsp_wfd_client_set_video_framerate_control(GstRTSPWFDClient *client, guint framerate) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->cframe_rate_control = framerate; +} + +void +gst_rtsp_wfd_client_set_rtp_port0(GstRTSPWFDClient *client, guint32 port) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->crtp_port0 = port; +} + +void +gst_rtsp_wfd_client_set_rtp_port1(GstRTSPWFDClient *client, guint32 port) +{ + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->crtp_port1 = port; +} diff --git a/gst/rtsp-server/rtsp-client-wfd.h b/gst/rtsp-server/rtsp-client-wfd.h new file mode 100644 index 0000000..25d96de --- /dev/null +++ b/gst/rtsp-server/rtsp-client-wfd.h @@ -0,0 +1,220 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include +#include + +#ifndef __GST_RTSP_WFD_CLIENT_H__ +#define __GST_RTSP_WFD_CLIENT_H__ + +G_BEGIN_DECLS + +typedef struct _GstRTSPWFDClient GstRTSPWFDClient; +typedef struct _GstRTSPWFDClientClass GstRTSPWFDClientClass; +typedef struct _GstRTSPWFDClientPrivate GstRTSPWFDClientPrivate; + +#include "rtsp-context.h" +#include "rtsp-mount-points.h" +#include "rtsp-sdp.h" +#include "rtsp-auth.h" +#include "rtsp-client.h" +#include "gstwfdmessage.h" + +#define GST_TYPE_RTSP_WFD_CLIENT (gst_rtsp_wfd_client_get_type ()) +#define GST_IS_RTSP_WFD_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_WFD_CLIENT)) +#define GST_IS_RTSP_WFD_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_WFD_CLIENT)) +#define GST_RTSP_WFD_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_WFD_CLIENT, GstRTSPWFDClientClass)) +#define GST_RTSP_WFD_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_WFD_CLIENT, GstRTSPWFDClient)) +#define GST_RTSP_WFD_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_WFD_CLIENT, GstRTSPWFDClientClass)) +#define GST_RTSP_WFD_CLIENT_CAST(obj) ((GstRTSPWFDClient*)(obj)) +#define GST_RTSP_WFD_CLIENT_CLASS_CAST(klass) ((GstRTSPWFDClientClass*)(klass)) + + +/** + * + */ +typedef enum { + WFD_TRIGGER_SETUP, + WFD_TRIGGER_PAUSE, + WFD_TRIGGER_TEARDOWN, + WFD_TRIGGER_PLAY +} GstWFDTriggerType; + +/** + * GstRTSPWFDClientSendFunc: + * @client: a #GstRTSPWFDClient + * @message: a #GstRTSPMessage + * @close: close the connection + * @user_data: user data when registering the callback + * + * This callback is called when @client wants to send @message. When @close is + * %TRUE, the connection should be closed when the message has been sent. + * + * Returns: %TRUE on success. + */ +typedef gboolean (*GstRTSPWFDClientSendFunc) (GstRTSPWFDClient *client, + GstRTSPMessage *message, + gboolean close, + gpointer user_data); + +/** + * GstRTSPWFDClient: + * + * The client object represents the connection and its state with a client. + */ +struct _GstRTSPWFDClient { + GstRTSPClient parent; + + gint supported_methods; + /*< private >*/ + GstRTSPWFDClientPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPWFDClientClass: + * @create_sdp: called when the SDP needs to be created for media. + * @configure_client_media: called when the stream in media needs to be configured. + * The default implementation will configure the blocksize on the payloader when + * spcified in the request headers. + * @configure_client_transport: called when the client transport needs to be + * configured. + * @params_set: set parameters. This function should also initialize the + * RTSP response(ctx->response) via a call to gst_rtsp_message_init_response() + * @params_get: get parameters. This function should also initialize the + * RTSP response(ctx->response) via a call to gst_rtsp_message_init_response() + * + * The client class structure. + */ +struct _GstRTSPWFDClientClass { + GstRTSPClientClass parent_class; + + GstRTSPResult (*prepare_resource) (GstRTSPWFDClient *client, GstRTSPContext *ctx); + GstRTSPResult (*confirm_resource) (GstRTSPWFDClient *client, GstRTSPContext *ctx); + + /* signals */ + void (*wfd_options_request) (GstRTSPWFDClient *client, GstRTSPContext *ctx); + void (*wfd_get_param_request) (GstRTSPWFDClient *client, GstRTSPContext *ctx); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +GType gst_rtsp_wfd_client_get_type (void); + +GstRTSPWFDClient * gst_rtsp_wfd_client_new (void); + +void gst_rtsp_wfd_client_set_host_address ( + GstRTSPWFDClient *client, const gchar * address); + +void gst_rtsp_wfd_client_start_wfd(GstRTSPWFDClient *client); +GstRTSPResult gst_rtsp_wfd_client_trigger_request ( + GstRTSPWFDClient * client, GstWFDTriggerType type); + +GstRTSPResult gst_rtsp_wfd_client_set_video_supported_resolution ( + GstRTSPWFDClient * client, guint64 supported_reso); +GstRTSPResult gst_rtsp_wfd_client_set_video_native_resolution ( + GstRTSPWFDClient * client, guint64 native_reso); +GstRTSPResult gst_rtsp_wfd_client_set_audio_codec ( + GstRTSPWFDClient * client, guint8 audio_codec); + +guint gst_rtsp_wfd_client_get_audio_codec(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_audio_freq(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_audio_channels(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_audio_bit_width(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_audio_latency(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_video_codec(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_video_native(GstRTSPWFDClient *client); +guint64 gst_rtsp_wfd_client_get_video_native_resolution(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_video_cea_resolution(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_video_vesa_resolution(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_video_hh_resolution(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_video_profile(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_video_level(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_video_latency(GstRTSPWFDClient *client); +guint32 gst_rtsp_wfd_client_get_video_max_height(GstRTSPWFDClient *client); +guint32 gst_rtsp_wfd_client_get_video_max_width(GstRTSPWFDClient *client); +guint32 gst_rtsp_wfd_client_get_video_framerate(GstRTSPWFDClient *client); +guint32 gst_rtsp_wfd_client_get_video_min_slice_size(GstRTSPWFDClient *client); +guint32 gst_rtsp_wfd_client_get_video_slice_enc_params(GstRTSPWFDClient *client); +guint gst_rtsp_wfd_client_get_video_framerate_control(GstRTSPWFDClient *client); +guint32 gst_rtsp_wfd_client_get_rtp_port0(GstRTSPWFDClient *client); +guint32 gst_rtsp_wfd_client_get_rtp_port1(GstRTSPWFDClient *client); +gboolean gst_rtsp_wfd_client_get_edid_supported(GstRTSPWFDClient *client); +guint32 gst_rtsp_wfd_client_get_edid_hresolution(GstRTSPWFDClient *client); +guint32 gst_rtsp_wfd_client_get_edid_vresolution(GstRTSPWFDClient *client); +gboolean gst_rtsp_wfd_client_get_protection_enabled(GstRTSPWFDClient *client); + +void gst_rtsp_wfd_client_set_audio_freq(GstRTSPWFDClient *client, guint freq); +void gst_rtsp_wfd_client_set_edid_supported(GstRTSPWFDClient *client, gboolean supported); +void gst_rtsp_wfd_client_set_edid_hresolution(GstRTSPWFDClient *client, guint32 reso); +void gst_rtsp_wfd_client_set_edid_vresolution(GstRTSPWFDClient *client, guint32 reso); +void gst_rtsp_wfd_client_set_protection_enabled(GstRTSPWFDClient *client, gboolean enable); +void gst_rtsp_wfd_client_set_keep_alive_flag(GstRTSPWFDClient *client, gboolean flag); +void gst_rtsp_wfd_client_set_aud_codec(GstRTSPWFDClient *client, guint acodec); +void gst_rtsp_wfd_client_set_audio_channels(GstRTSPWFDClient *client, guint channels); +void gst_rtsp_wfd_client_set_audio_bit_width(GstRTSPWFDClient *client, guint bwidth); +void gst_rtsp_wfd_client_set_audio_latency(GstRTSPWFDClient *client, guint latency); +void gst_rtsp_wfd_client_set_video_codec(GstRTSPWFDClient *client, guint vcodec); +void gst_rtsp_wfd_client_set_video_native(GstRTSPWFDClient *client, guint native); +void gst_rtsp_wfd_client_set_vid_native_resolution(GstRTSPWFDClient *client, guint64 res); +void gst_rtsp_wfd_client_set_video_cea_resolution(GstRTSPWFDClient *client, guint res); +void gst_rtsp_wfd_client_set_video_vesa_resolution(GstRTSPWFDClient *client, guint res); +void gst_rtsp_wfd_client_set_video_hh_resolution(GstRTSPWFDClient *client, guint res); +void gst_rtsp_wfd_client_set_video_profile(GstRTSPWFDClient *client, guint profile); +void gst_rtsp_wfd_client_set_video_level(GstRTSPWFDClient *client, guint level); +void gst_rtsp_wfd_client_set_video_latency(GstRTSPWFDClient *client, guint latency); +void gst_rtsp_wfd_client_set_video_max_height(GstRTSPWFDClient *client, guint32 height); +void gst_rtsp_wfd_client_set_video_max_width(GstRTSPWFDClient *client, guint32 width); +void gst_rtsp_wfd_client_set_video_framerate(GstRTSPWFDClient *client, guint32 framerate); +void gst_rtsp_wfd_client_set_video_min_slice_size(GstRTSPWFDClient *client, guint32 slice_size); +void gst_rtsp_wfd_client_set_video_slice_enc_params(GstRTSPWFDClient *client, guint32 enc_params); +void gst_rtsp_wfd_client_set_video_framerate_control(GstRTSPWFDClient *client, guint framerate); +void gst_rtsp_wfd_client_set_rtp_port0(GstRTSPWFDClient *client, guint32 port); +void gst_rtsp_wfd_client_set_rtp_port1(GstRTSPWFDClient *client, guint32 port); + +/** + * GstRTSPWFDClientSessionFilterFunc: + * @client: a #GstRTSPWFDClient object + * @sess: a #GstRTSPSession in @client + * @user_data: user data that has been given to gst_rtsp_wfd_client_session_filter() + * + * This function will be called by the gst_rtsp_wfd_client_session_filter(). An + * implementation should return a value of #GstRTSPFilterResult. + * + * When this function returns #GST_RTSP_FILTER_REMOVE, @sess will be removed + * from @client. + * + * A return value of #GST_RTSP_FILTER_KEEP will leave @sess untouched in + * @client. + * + * A value of #GST_RTSP_FILTER_REF will add @sess to the result #GList of + * gst_rtsp_wfd_client_session_filter(). + * + * Returns: a #GstRTSPFilterResult. + */ +typedef GstRTSPFilterResult (*GstRTSPWFDClientSessionFilterFunc) (GstRTSPWFDClient *client, + GstRTSPSession *sess, + gpointer user_data); + + + +G_END_DECLS + +#endif /* __GST_RTSP_WFD_CLIENT_H__ */ diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c new file mode 100644 index 0000000..b169d4b --- /dev/null +++ b/gst/rtsp-server/rtsp-client.c @@ -0,0 +1,3568 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-client + * @short_description: A client connection state + * @see_also: #GstRTSPServer, #GstRTSPThreadPool + * + * The client object handles the connection with a client for as long as a TCP + * connection is open. + * + * A #GstRTSPClient is created by #GstRTSPServer when a new connection is + * accepted and it inherits the #GstRTSPMountPoints, #GstRTSPSessionPool, + * #GstRTSPAuth and #GstRTSPThreadPool from the server. + * + * The client connection should be configured with the #GstRTSPConnection using + * gst_rtsp_client_set_connection() before it can be attached to a #GMainContext + * using gst_rtsp_client_attach(). From then on the client will handle requests + * on the connection. + * + * Use gst_rtsp_client_session_filter() to iterate or modify all the + * #GstRTSPSession objects managed by the client object. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include +#include + +#include + +#include "rtsp-client.h" +#include "rtsp-sdp.h" +#include "rtsp-params.h" + +#define GST_RTSP_CLIENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_CLIENT, GstRTSPClientPrivate)) + +/* locking order: + * send_lock, lock, tunnels_lock + */ + +struct _GstRTSPClientPrivate +{ + GMutex lock; /* protects everything else */ + GMutex send_lock; + GMutex watch_lock; + GstRTSPConnection *connection; + GstRTSPWatch *watch; + GMainContext *watch_context; + guint close_seq; + gchar *server_ip; + gboolean is_ipv6; + + GstRTSPClientSendFunc send_func; /* protected by send_lock */ + gpointer send_data; /* protected by send_lock */ + GDestroyNotify send_notify; /* protected by send_lock */ + + GstRTSPSessionPool *session_pool; + gulong session_removed_id; + GstRTSPMountPoints *mount_points; + GstRTSPAuth *auth; + GstRTSPThreadPool *thread_pool; + + /* used to cache the media in the last requested DESCRIBE so that + * we can pick it up in the next SETUP immediately */ + gchar *path; + GstRTSPMedia *media; + + GList *transports; + GList *sessions; + guint sessions_cookie; + + gboolean drop_backlog; +}; + +static GMutex tunnels_lock; +static GHashTable *tunnels; /* protected by tunnels_lock */ + +#define DEFAULT_SESSION_POOL NULL +#define DEFAULT_MOUNT_POINTS NULL +#define DEFAULT_DROP_BACKLOG TRUE + +enum +{ + PROP_0, + PROP_SESSION_POOL, + PROP_MOUNT_POINTS, + PROP_DROP_BACKLOG, + PROP_LAST +}; + +enum +{ + SIGNAL_CLOSED, + SIGNAL_NEW_SESSION, + SIGNAL_OPTIONS_REQUEST, + SIGNAL_DESCRIBE_REQUEST, + SIGNAL_SETUP_REQUEST, + SIGNAL_PLAY_REQUEST, + SIGNAL_PAUSE_REQUEST, + SIGNAL_TEARDOWN_REQUEST, + SIGNAL_SET_PARAMETER_REQUEST, + SIGNAL_GET_PARAMETER_REQUEST, + SIGNAL_HANDLE_RESPONSE, + SIGNAL_SEND_MESSAGE, + SIGNAL_LAST +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_client_debug); +#define GST_CAT_DEFAULT rtsp_client_debug + +static guint gst_rtsp_client_signals[SIGNAL_LAST] = { 0 }; + +static void gst_rtsp_client_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_client_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); +static void gst_rtsp_client_finalize (GObject * obj); + +static GstSDPMessage *create_sdp (GstRTSPClient * client, GstRTSPMedia * media); +static void unlink_session_transports (GstRTSPClient * client, + GstRTSPSession * session, GstRTSPSessionMedia * sessmedia); +static gboolean default_configure_client_media (GstRTSPClient * client, + GstRTSPMedia * media, GstRTSPStream * stream, GstRTSPContext * ctx); +static gboolean default_configure_client_transport (GstRTSPClient * client, + GstRTSPContext * ctx, GstRTSPTransport * ct); +static GstRTSPResult default_params_set (GstRTSPClient * client, + GstRTSPContext * ctx); +static GstRTSPResult default_params_get (GstRTSPClient * client, + GstRTSPContext * ctx); +static gchar *default_make_path_from_uri (GstRTSPClient * client, + const GstRTSPUrl * uri); +static gboolean default_handle_options_request (GstRTSPClient * client, + GstRTSPContext * ctx); +static gboolean default_handle_set_param_request (GstRTSPClient * client, + GstRTSPContext * ctx); +static gboolean default_handle_get_param_request (GstRTSPClient * client, + GstRTSPContext * ctx); +static void client_session_removed (GstRTSPSessionPool * pool, + GstRTSPSession * session, GstRTSPClient * client); + +G_DEFINE_TYPE (GstRTSPClient, gst_rtsp_client, G_TYPE_OBJECT); + +static void +gst_rtsp_client_class_init (GstRTSPClientClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPClientPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gst_rtsp_client_get_property; + gobject_class->set_property = gst_rtsp_client_set_property; + gobject_class->finalize = gst_rtsp_client_finalize; + + klass->create_sdp = create_sdp; + klass->configure_client_media = default_configure_client_media; + klass->configure_client_transport = default_configure_client_transport; + klass->params_set = default_params_set; + klass->params_get = default_params_get; + klass->make_path_from_uri = default_make_path_from_uri; + klass->handle_options_request = default_handle_options_request; + klass->handle_set_param_request = default_handle_set_param_request; + klass->handle_get_param_request = default_handle_get_param_request; + + g_object_class_install_property (gobject_class, PROP_SESSION_POOL, + g_param_spec_object ("session-pool", "Session Pool", + "The session pool to use for client session", + GST_TYPE_RTSP_SESSION_POOL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MOUNT_POINTS, + g_param_spec_object ("mount-points", "Mount Points", + "The mount points to use for client session", + GST_TYPE_RTSP_MOUNT_POINTS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_DROP_BACKLOG, + g_param_spec_boolean ("drop-backlog", "Drop Backlog", + "Drop data when the backlog queue is full", + DEFAULT_DROP_BACKLOG, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_rtsp_client_signals[SIGNAL_CLOSED] = + g_signal_new ("closed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstRTSPClientClass, closed), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE); + + gst_rtsp_client_signals[SIGNAL_NEW_SESSION] = + g_signal_new ("new-session", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstRTSPClientClass, new_session), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_RTSP_SESSION); + + gst_rtsp_client_signals[SIGNAL_OPTIONS_REQUEST] = + g_signal_new ("options-request", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, options_request), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_RTSP_CONTEXT); + + gst_rtsp_client_signals[SIGNAL_DESCRIBE_REQUEST] = + g_signal_new ("describe-request", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, describe_request), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_RTSP_CONTEXT); + + gst_rtsp_client_signals[SIGNAL_SETUP_REQUEST] = + g_signal_new ("setup-request", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, setup_request), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_RTSP_CONTEXT); + + gst_rtsp_client_signals[SIGNAL_PLAY_REQUEST] = + g_signal_new ("play-request", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, play_request), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_RTSP_CONTEXT); + + gst_rtsp_client_signals[SIGNAL_PAUSE_REQUEST] = + g_signal_new ("pause-request", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, pause_request), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_RTSP_CONTEXT); + + gst_rtsp_client_signals[SIGNAL_TEARDOWN_REQUEST] = + g_signal_new ("teardown-request", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, teardown_request), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_RTSP_CONTEXT); + + gst_rtsp_client_signals[SIGNAL_SET_PARAMETER_REQUEST] = + g_signal_new ("set-parameter-request", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, + set_parameter_request), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT); + + gst_rtsp_client_signals[SIGNAL_GET_PARAMETER_REQUEST] = + g_signal_new ("get-parameter-request", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, + get_parameter_request), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT); + + gst_rtsp_client_signals[SIGNAL_HANDLE_RESPONSE] = + g_signal_new ("handle-response", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, + handle_response), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT); + + /** + * GstRTSPClient::send-message: + * @client: The RTSP client + * @session: (type GstRtspServer.RTSPSession): The session + * @message: (type GstRtsp.RTSPMessage): The message + */ + gst_rtsp_client_signals[SIGNAL_SEND_MESSAGE] = + g_signal_new ("send-message", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 2, GST_TYPE_RTSP_CONTEXT, G_TYPE_POINTER); + + tunnels = + g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + g_mutex_init (&tunnels_lock); + + GST_DEBUG_CATEGORY_INIT (rtsp_client_debug, "rtspclient", 0, "GstRTSPClient"); +} + +static void +gst_rtsp_client_init (GstRTSPClient * client) +{ + GstRTSPClientPrivate *priv = GST_RTSP_CLIENT_GET_PRIVATE (client); + + client->priv = priv; + + g_mutex_init (&priv->lock); + g_mutex_init (&priv->send_lock); + g_mutex_init (&priv->watch_lock); + priv->close_seq = 0; + priv->drop_backlog = DEFAULT_DROP_BACKLOG; +} + +static GstRTSPFilterResult +filter_session_media (GstRTSPSession * sess, GstRTSPSessionMedia * sessmedia, + gpointer user_data) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + + gst_rtsp_session_media_set_state (sessmedia, GST_STATE_NULL); + unlink_session_transports (client, sess, sessmedia); + + /* unmanage the media in the session */ + return GST_RTSP_FILTER_REMOVE; +} + +static void +client_watch_session (GstRTSPClient * client, GstRTSPSession * session) +{ + GstRTSPClientPrivate *priv = client->priv; + + g_mutex_lock (&priv->lock); + /* check if we already know about this session */ + if (g_list_find (priv->sessions, session) == NULL) { + GST_INFO ("watching session %p", session); + + priv->sessions = g_list_prepend (priv->sessions, g_object_ref (session)); + priv->sessions_cookie++; + + /* connect removed session handler, it will be disconnected when the last + * session gets removed */ + if (priv->session_removed_id == 0) + priv->session_removed_id = g_signal_connect_data (priv->session_pool, + "session-removed", G_CALLBACK (client_session_removed), + g_object_ref (client), (GClosureNotify) g_object_unref, 0); + } + g_mutex_unlock (&priv->lock); + + return; +} + +/* should be called with lock */ +static void +client_unwatch_session (GstRTSPClient * client, GstRTSPSession * session, + GList * link) +{ + GstRTSPClientPrivate *priv = client->priv; + + GST_INFO ("client %p: unwatch session %p", client, session); + + if (link == NULL) { + link = g_list_find (priv->sessions, session); + if (link == NULL) + return; + } + + priv->sessions = g_list_delete_link (priv->sessions, link); + priv->sessions_cookie++; + + /* if this was the last session, disconnect the handler. + * This will also drop the extra client ref */ + if (!priv->sessions) { + g_signal_handler_disconnect (priv->session_pool, priv->session_removed_id); + priv->session_removed_id = 0; + } + + /* unlink all media managed in this session */ + gst_rtsp_session_filter (session, filter_session_media, client); + + /* remove the session */ + g_object_unref (session); +} + +static GstRTSPFilterResult +cleanup_session (GstRTSPClient * client, GstRTSPSession * sess, + gpointer user_data) +{ + return GST_RTSP_FILTER_REMOVE; +} + +/* A client is finalized when the connection is broken */ +static void +gst_rtsp_client_finalize (GObject * obj) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (obj); + GstRTSPClientPrivate *priv = client->priv; + + GST_INFO ("finalize client %p", client); + + if (priv->watch) + gst_rtsp_watch_set_flushing (priv->watch, TRUE); + gst_rtsp_client_set_send_func (client, NULL, NULL, NULL); + + if (priv->watch) + g_source_destroy ((GSource *) priv->watch); + + if (priv->watch_context) + g_main_context_unref (priv->watch_context); + + /* all sessions should have been removed by now. We keep a ref to + * the client object for the session removed handler. The ref is + * dropped when the last session is removed from the list. */ + g_assert (priv->sessions == NULL); + g_assert (priv->session_removed_id == 0); + + if (priv->connection) + gst_rtsp_connection_free (priv->connection); + if (priv->session_pool) { + g_object_unref (priv->session_pool); + } + if (priv->mount_points) + g_object_unref (priv->mount_points); + if (priv->auth) + g_object_unref (priv->auth); + if (priv->thread_pool) + g_object_unref (priv->thread_pool); + + if (priv->path) + g_free (priv->path); + if (priv->media) { + gst_rtsp_media_unprepare (priv->media); + g_object_unref (priv->media); + } + + g_free (priv->server_ip); + g_mutex_clear (&priv->lock); + g_mutex_clear (&priv->send_lock); + g_mutex_clear (&priv->watch_lock); + + G_OBJECT_CLASS (gst_rtsp_client_parent_class)->finalize (obj); +} + +static void +gst_rtsp_client_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (object); + GstRTSPClientPrivate *priv = client->priv; + + switch (propid) { + case PROP_SESSION_POOL: + g_value_take_object (value, gst_rtsp_client_get_session_pool (client)); + break; + case PROP_MOUNT_POINTS: + g_value_take_object (value, gst_rtsp_client_get_mount_points (client)); + break; + case PROP_DROP_BACKLOG: + g_value_set_boolean (value, priv->drop_backlog); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_client_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (object); + GstRTSPClientPrivate *priv = client->priv; + + switch (propid) { + case PROP_SESSION_POOL: + gst_rtsp_client_set_session_pool (client, g_value_get_object (value)); + break; + case PROP_MOUNT_POINTS: + gst_rtsp_client_set_mount_points (client, g_value_get_object (value)); + break; + case PROP_DROP_BACKLOG: + g_mutex_lock (&priv->lock); + priv->drop_backlog = g_value_get_boolean (value); + g_mutex_unlock (&priv->lock); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +/** + * gst_rtsp_client_new: + * + * Create a new #GstRTSPClient instance. + * + * Returns: (transfer full): a new #GstRTSPClient + */ +GstRTSPClient * +gst_rtsp_client_new (void) +{ + GstRTSPClient *result; + + result = g_object_new (GST_TYPE_RTSP_CLIENT, NULL); + + return result; +} + +static void +send_message (GstRTSPClient * client, GstRTSPContext * ctx, + GstRTSPMessage * message, gboolean close) +{ + GstRTSPClientPrivate *priv = client->priv; + + gst_rtsp_message_add_header (message, GST_RTSP_HDR_SERVER, + "GStreamer RTSP server"); + + /* remove any previous header */ + gst_rtsp_message_remove_header (message, GST_RTSP_HDR_SESSION, -1); + + /* add the new session header for new session ids */ + if (ctx->session) { + gst_rtsp_message_take_header (message, GST_RTSP_HDR_SESSION, + gst_rtsp_session_get_header (ctx->session)); + } + + if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) { + gst_rtsp_message_dump (message); + } + + if (close) + gst_rtsp_message_add_header (message, GST_RTSP_HDR_CONNECTION, "close"); + + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_SEND_MESSAGE], + 0, ctx, message); + + g_mutex_lock (&priv->send_lock); + if (priv->send_func) + priv->send_func (client, message, close, priv->send_data); + g_mutex_unlock (&priv->send_lock); + + gst_rtsp_message_unset (message); +} + +static void +send_generic_response (GstRTSPClient * client, GstRTSPStatusCode code, + GstRTSPContext * ctx) +{ + gst_rtsp_message_init_response (ctx->response, code, + gst_rtsp_status_as_text (code), ctx->request); + + ctx->session = NULL; + + send_message (client, ctx, ctx->response, FALSE); +} + +static void +send_option_not_supported_response (GstRTSPClient * client, + GstRTSPContext * ctx, const gchar * unsupported_options) +{ + GstRTSPStatusCode code = GST_RTSP_STS_OPTION_NOT_SUPPORTED; + + gst_rtsp_message_init_response (ctx->response, code, + gst_rtsp_status_as_text (code), ctx->request); + + if (unsupported_options != NULL) { + gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_UNSUPPORTED, + unsupported_options); + } + + ctx->session = NULL; + + send_message (client, ctx, ctx->response, FALSE); +} + +static gboolean +paths_are_equal (const gchar * path1, const gchar * path2, gint len2) +{ + if (path1 == NULL || path2 == NULL) + return FALSE; + + if (strlen (path1) != len2) + return FALSE; + + if (strncmp (path1, path2, len2)) + return FALSE; + + return TRUE; +} + +/* this function is called to initially find the media for the DESCRIBE request + * but is cached for when the same client (without breaking the connection) is + * doing a setup for the exact same url. */ +static GstRTSPMedia * +find_media (GstRTSPClient * client, GstRTSPContext * ctx, gchar * path, + gint * matched) +{ + GstRTSPClientPrivate *priv = client->priv; + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + gint path_len; + + /* find the longest matching factory for the uri first */ + if (!(factory = gst_rtsp_mount_points_match (priv->mount_points, + path, matched))) + goto no_factory; + + ctx->factory = factory; + + if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS)) + goto no_factory_access; + + if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT)) + goto not_authorized; + + if (matched) + path_len = *matched; + else + path_len = strlen (path); + + if (!paths_are_equal (priv->path, path, path_len)) { + GstRTSPThread *thread; + + /* remove any previously cached values before we try to construct a new + * media for uri */ + if (priv->path) + g_free (priv->path); + priv->path = NULL; + if (priv->media) { + gst_rtsp_media_unprepare (priv->media); + g_object_unref (priv->media); + } + priv->media = NULL; + + /* prepare the media and add it to the pipeline */ + if (!(media = gst_rtsp_media_factory_construct (factory, ctx->uri))) + goto no_media; + + ctx->media = media; + + thread = gst_rtsp_thread_pool_get_thread (priv->thread_pool, + GST_RTSP_THREAD_TYPE_MEDIA, ctx); + if (thread == NULL) + goto no_thread; + + /* prepare the media */ + if (!(gst_rtsp_media_prepare (media, thread))) + goto no_prepare; + + /* now keep track of the uri and the media */ + priv->path = g_strndup (path, path_len); + priv->media = media; + } else { + /* we have seen this path before, used cached media */ + media = priv->media; + ctx->media = media; + GST_INFO ("reusing cached media %p for path %s", media, priv->path); + } + + g_object_unref (factory); + ctx->factory = NULL; + + if (media) + g_object_ref (media); + + return media; + + /* ERRORS */ +no_factory: + { + GST_ERROR ("client %p: no factory for path %s", client, path); + send_generic_response (client, GST_RTSP_STS_NOT_FOUND, ctx); + return NULL; + } +no_factory_access: + { + GST_ERROR ("client %p: not authorized to see factory path %s", client, + path); + /* error reply is already sent */ + return NULL; + } +not_authorized: + { + GST_ERROR ("client %p: not authorized for factory path %s", client, path); + /* error reply is already sent */ + return NULL; + } +no_media: + { + GST_ERROR ("client %p: can't create media", client); + send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx); + g_object_unref (factory); + ctx->factory = NULL; + return NULL; + } +no_thread: + { + GST_ERROR ("client %p: can't create thread", client); + send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx); + g_object_unref (media); + ctx->media = NULL; + g_object_unref (factory); + ctx->factory = NULL; + return NULL; + } +no_prepare: + { + GST_ERROR ("client %p: can't prepare media", client); + send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx); + g_object_unref (media); + ctx->media = NULL; + g_object_unref (factory); + ctx->factory = NULL; + return NULL; + } +} + +static gboolean +do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client) +{ + GstRTSPClientPrivate *priv = client->priv; + GstRTSPMessage message = { 0 }; + GstMapInfo map_info; + guint8 *data; + guint usize; + + gst_rtsp_message_init_data (&message, channel); + + /* FIXME, need some sort of iovec RTSPMessage here */ + if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) + return FALSE; + + gst_rtsp_message_take_body (&message, map_info.data, map_info.size); + + g_mutex_lock (&priv->send_lock); + if (priv->send_func) + priv->send_func (client, &message, FALSE, priv->send_data); + g_mutex_unlock (&priv->send_lock); + + gst_rtsp_message_steal_body (&message, &data, &usize); + gst_buffer_unmap (buffer, &map_info); + + gst_rtsp_message_unset (&message); + + return TRUE; +} + +static void +link_transport (GstRTSPClient * client, GstRTSPSession * session, + GstRTSPStreamTransport * trans) +{ + GstRTSPClientPrivate *priv = client->priv; + + GST_DEBUG ("client %p: linking transport %p", client, trans); + + gst_rtsp_stream_transport_set_callbacks (trans, + (GstRTSPSendFunc) do_send_data, + (GstRTSPSendFunc) do_send_data, client, NULL); + + priv->transports = g_list_prepend (priv->transports, trans); + + /* make sure our session can't expire */ + gst_rtsp_session_prevent_expire (session); +} + +static void +link_session_transports (GstRTSPClient * client, GstRTSPSession * session, + GstRTSPSessionMedia * sessmedia) +{ + guint n_streams, i; + + n_streams = + gst_rtsp_media_n_streams (gst_rtsp_session_media_get_media (sessmedia)); + for (i = 0; i < n_streams; i++) { + GstRTSPStreamTransport *trans; + const GstRTSPTransport *tr; + + /* get the transport, if there is no transport configured, skip this stream */ + trans = gst_rtsp_session_media_get_transport (sessmedia, i); + if (trans == NULL) + continue; + + tr = gst_rtsp_stream_transport_get_transport (trans); + + if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) { + /* for TCP, link the stream to the TCP connection of the client */ + link_transport (client, session, trans); + } + } +} + +static void +unlink_transport (GstRTSPClient * client, GstRTSPSession * session, + GstRTSPStreamTransport * trans) +{ + GstRTSPClientPrivate *priv = client->priv; + + GST_DEBUG ("client %p: unlinking transport %p", client, trans); + + gst_rtsp_stream_transport_set_callbacks (trans, NULL, NULL, NULL, NULL); + + priv->transports = g_list_remove (priv->transports, trans); + + /* our session can now expire */ + gst_rtsp_session_allow_expire (session); +} + +static void +unlink_session_transports (GstRTSPClient * client, GstRTSPSession * session, + GstRTSPSessionMedia * sessmedia) +{ + guint n_streams, i; + + n_streams = + gst_rtsp_media_n_streams (gst_rtsp_session_media_get_media (sessmedia)); + for (i = 0; i < n_streams; i++) { + GstRTSPStreamTransport *trans; + const GstRTSPTransport *tr; + + /* get the transport, if there is no transport configured, skip this stream */ + trans = gst_rtsp_session_media_get_transport (sessmedia, i); + if (trans == NULL) + continue; + + tr = gst_rtsp_stream_transport_get_transport (trans); + + if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) { + /* for TCP, unlink the stream from the TCP connection of the client */ + unlink_transport (client, session, trans); + } + } +} + +/** + * gst_rtsp_client_close: + * @client: a #GstRTSPClient + * + * Close the connection of @client and remove all media it was managing. + * + * Since: 1.4 + */ +void +gst_rtsp_client_close (GstRTSPClient * client) +{ + GstRTSPClientPrivate *priv = client->priv; + const gchar *tunnelid; + + GST_DEBUG ("client %p: closing connection", client); + + if (priv->connection) { + if ((tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection))) { + g_mutex_lock (&tunnels_lock); + /* remove from tunnelids */ + g_hash_table_remove (tunnels, tunnelid); + g_mutex_unlock (&tunnels_lock); + } + gst_rtsp_connection_close (priv->connection); + } + + /* connection is now closed, destroy the watch which will also cause the + * closed signal to be emitted */ + if (priv->watch) { + GST_DEBUG ("client %p: destroying watch", client); + g_source_destroy ((GSource *) priv->watch); + priv->watch = NULL; + gst_rtsp_client_set_send_func (client, NULL, NULL, NULL); + } +} + +static gchar * +default_make_path_from_uri (GstRTSPClient * client, const GstRTSPUrl * uri) +{ + gchar *path; + + if (uri->query) + path = g_strconcat (uri->abspath, "?", uri->query, NULL); + else + path = g_strdup (uri->abspath); + + return path; +} + +static gboolean +handle_teardown_request (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPClientPrivate *priv = client->priv; + GstRTSPClientClass *klass; + GstRTSPSession *session; + GstRTSPSessionMedia *sessmedia; + GstRTSPStatusCode code; + gchar *path; + gint matched; + gboolean keep_session; + + if (!ctx->session) + goto no_session; + + session = ctx->session; + + if (!ctx->uri) + goto no_uri; + + klass = GST_RTSP_CLIENT_GET_CLASS (client); + path = klass->make_path_from_uri (client, ctx->uri); + + /* get a handle to the configuration of the media in the session */ + sessmedia = gst_rtsp_session_get_media (session, path, &matched); + if (!sessmedia) + goto not_found; + + /* only aggregate control for now.. */ + if (path[matched] != '\0') + goto no_aggregate; + + g_free (path); + + ctx->sessmedia = sessmedia; + + /* we emit the signal before closing the connection */ + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_TEARDOWN_REQUEST], + 0, ctx); + + /* make sure we unblock the backlog and don't accept new messages + * on the watch */ + if (priv->watch != NULL) + gst_rtsp_watch_set_flushing (priv->watch, TRUE); + + /* unlink the all TCP callbacks */ + unlink_session_transports (client, session, sessmedia); + + gst_rtsp_session_media_set_state (sessmedia, GST_STATE_NULL); + + /* allow messages again so that we can send the reply */ + if (priv->watch != NULL) + gst_rtsp_watch_set_flushing (priv->watch, FALSE); + + /* unmanage the media in the session, returns false if all media session + * are torn down. */ + keep_session = gst_rtsp_session_release_media (session, sessmedia); + + /* construct the response now */ + code = GST_RTSP_STS_OK; + gst_rtsp_message_init_response (ctx->response, code, + gst_rtsp_status_as_text (code), ctx->request); + + send_message (client, ctx, ctx->response, TRUE); + + if (!keep_session) { + /* remove the session */ + gst_rtsp_session_pool_remove (priv->session_pool, session); + } + + return TRUE; + + /* ERRORS */ +no_session: + { + GST_ERROR ("client %p: no session", client); + send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx); + return FALSE; + } +no_uri: + { + GST_ERROR ("client %p: no uri supplied", client); + send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx); + return FALSE; + } +not_found: + { + GST_ERROR ("client %p: no media for uri", client); + send_generic_response (client, GST_RTSP_STS_NOT_FOUND, ctx); + g_free (path); + return FALSE; + } +no_aggregate: + { + GST_ERROR ("client %p: no aggregate path %s", client, path); + send_generic_response (client, + GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx); + g_free (path); + return FALSE; + } +} + +static GstRTSPResult +default_params_set (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPResult res; + + res = gst_rtsp_params_set (client, ctx); + + return res; +} + +static GstRTSPResult +default_params_get (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPResult res; + + res = gst_rtsp_params_get (client, ctx); + + return res; +} + +static gboolean +default_handle_get_param_request (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPResult res; + guint8 *data; + guint size; + + res = gst_rtsp_message_get_body (ctx->request, &data, &size); + if (res != GST_RTSP_OK) + goto bad_request; + + if (size == 0) { + /* no body, keep-alive request */ + send_generic_response (client, GST_RTSP_STS_OK, ctx); + } else { + /* there is a body, handle the params */ + res = GST_RTSP_CLIENT_GET_CLASS (client)->params_get (client, ctx); + if (res != GST_RTSP_OK) + goto bad_request; + + send_message (client, ctx, ctx->response, FALSE); + } + + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_GET_PARAMETER_REQUEST], + 0, ctx); + + return TRUE; + + /* ERRORS */ +bad_request: + { + GST_ERROR ("client %p: bad request", client); + send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx); + return FALSE; + } +} + +static gboolean +default_handle_set_param_request (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPResult res; + guint8 *data; + guint size; + + res = gst_rtsp_message_get_body (ctx->request, &data, &size); + if (res != GST_RTSP_OK) + goto bad_request; + + if (size == 0) { + /* no body, keep-alive request */ + send_generic_response (client, GST_RTSP_STS_OK, ctx); + } else { + /* there is a body, handle the params */ + res = GST_RTSP_CLIENT_GET_CLASS (client)->params_set (client, ctx); + if (res != GST_RTSP_OK) + goto bad_request; + + send_message (client, ctx, ctx->response, FALSE); + } + + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_SET_PARAMETER_REQUEST], + 0, ctx); + + return TRUE; + + /* ERRORS */ +bad_request: + { + GST_ERROR ("client %p: bad request", client); + send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx); + return FALSE; + } +} + +static gboolean +handle_pause_request (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPSession *session; + GstRTSPClientClass *klass; + GstRTSPSessionMedia *sessmedia; + GstRTSPStatusCode code; + GstRTSPState rtspstate; + gchar *path; + gint matched; + + if (!(session = ctx->session)) + goto no_session; + + if (!ctx->uri) + goto no_uri; + + klass = GST_RTSP_CLIENT_GET_CLASS (client); + path = klass->make_path_from_uri (client, ctx->uri); + + /* get a handle to the configuration of the media in the session */ + sessmedia = gst_rtsp_session_get_media (session, path, &matched); + if (!sessmedia) + goto not_found; + + if (path[matched] != '\0') + goto no_aggregate; + + g_free (path); + + ctx->sessmedia = sessmedia; + + rtspstate = gst_rtsp_session_media_get_rtsp_state (sessmedia); + /* the session state must be playing or recording */ + if (rtspstate != GST_RTSP_STATE_PLAYING && + rtspstate != GST_RTSP_STATE_RECORDING) + goto invalid_state; + + /* unlink the all TCP callbacks */ + unlink_session_transports (client, session, sessmedia); + + /* then pause sending */ + gst_rtsp_session_media_set_state (sessmedia, GST_STATE_PAUSED); + + /* construct the response now */ + code = GST_RTSP_STS_OK; + gst_rtsp_message_init_response (ctx->response, code, + gst_rtsp_status_as_text (code), ctx->request); + + send_message (client, ctx, ctx->response, FALSE); + + /* the state is now READY */ + gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_READY); + + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PAUSE_REQUEST], 0, ctx); + + return TRUE; + + /* ERRORS */ +no_session: + { + GST_ERROR ("client %p: no seesion", client); + send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx); + return FALSE; + } +no_uri: + { + GST_ERROR ("client %p: no uri supplied", client); + send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx); + return FALSE; + } +not_found: + { + GST_ERROR ("client %p: no media for uri", client); + send_generic_response (client, GST_RTSP_STS_NOT_FOUND, ctx); + g_free (path); + return FALSE; + } +no_aggregate: + { + GST_ERROR ("client %p: no aggregate path %s", client, path); + send_generic_response (client, + GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx); + g_free (path); + return FALSE; + } +invalid_state: + { + GST_ERROR ("client %p: not PLAYING or RECORDING", client); + send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, + ctx); + return FALSE; + } +} + +/* convert @url and @path to a URL used as a content base for the factory + * located at @path */ +static gchar * +make_base_url (GstRTSPClient * client, GstRTSPUrl * url, const gchar * path) +{ + GstRTSPUrl tmp; + gchar *result; + const gchar *trail; + + /* check for trailing '/' and append one */ + trail = (path[strlen (path) - 1] != '/' ? "/" : ""); + + tmp = *url; + tmp.user = NULL; + tmp.passwd = NULL; + tmp.abspath = g_strdup_printf ("%s%s", path, trail); + tmp.query = NULL; + result = gst_rtsp_url_get_request_uri (&tmp); + g_free (tmp.abspath); + + return result; +} + +static gboolean +handle_play_request (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPSession *session; + GstRTSPClientClass *klass; + GstRTSPSessionMedia *sessmedia; + GstRTSPMedia *media; + GstRTSPStatusCode code; + GstRTSPUrl *uri; + gchar *str; + GstRTSPTimeRange *range; + GstRTSPResult res; + GstRTSPState rtspstate; + GstRTSPRangeUnit unit = GST_RTSP_RANGE_NPT; + gchar *path, *rtpinfo; + gint matched; + + if (!(session = ctx->session)) + goto no_session; + + if (!(uri = ctx->uri)) + goto no_uri; + + klass = GST_RTSP_CLIENT_GET_CLASS (client); + path = klass->make_path_from_uri (client, uri); + + /* get a handle to the configuration of the media in the session */ + sessmedia = gst_rtsp_session_get_media (session, path, &matched); + if (!sessmedia) + goto not_found; + + if (path[matched] != '\0') + goto no_aggregate; + + g_free (path); + + ctx->sessmedia = sessmedia; + ctx->media = media = gst_rtsp_session_media_get_media (sessmedia); + + /* the session state must be playing or ready */ + rtspstate = gst_rtsp_session_media_get_rtsp_state (sessmedia); + if (rtspstate != GST_RTSP_STATE_PLAYING && rtspstate != GST_RTSP_STATE_READY) + goto invalid_state; + + /* in play we first unsuspend, media could be suspended from SDP or PAUSED */ + if (!gst_rtsp_media_unsuspend (media)) + goto unsuspend_failed; + + /* parse the range header if we have one */ + res = gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_RANGE, &str, 0); + if (res == GST_RTSP_OK) { + if (gst_rtsp_range_parse (str, &range) == GST_RTSP_OK) { + /* we have a range, seek to the position */ + unit = range->unit; + gst_rtsp_media_seek (media, range); + gst_rtsp_range_free (range); + } + } + + /* link the all TCP callbacks */ + link_session_transports (client, session, sessmedia); + + /* grab RTPInfo from the media now */ + rtpinfo = gst_rtsp_session_media_get_rtpinfo (sessmedia); + + /* construct the response now */ + code = GST_RTSP_STS_OK; + gst_rtsp_message_init_response (ctx->response, code, + gst_rtsp_status_as_text (code), ctx->request); + + /* add the RTP-Info header */ + if (rtpinfo) + gst_rtsp_message_take_header (ctx->response, GST_RTSP_HDR_RTP_INFO, + rtpinfo); + + /* add the range */ + str = gst_rtsp_media_get_range_string (media, TRUE, unit); + if (str) + gst_rtsp_message_take_header (ctx->response, GST_RTSP_HDR_RANGE, str); + + send_message (client, ctx, ctx->response, FALSE); + + /* start playing after sending the response */ + gst_rtsp_session_media_set_state (sessmedia, GST_STATE_PLAYING); + + gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_PLAYING); + + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PLAY_REQUEST], 0, ctx); + + return TRUE; + + /* ERRORS */ +no_session: + { + GST_ERROR ("client %p: no session", client); + send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx); + return FALSE; + } +no_uri: + { + GST_ERROR ("client %p: no uri supplied", client); + send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx); + return FALSE; + } +not_found: + { + GST_ERROR ("client %p: media not found", client); + send_generic_response (client, GST_RTSP_STS_NOT_FOUND, ctx); + return FALSE; + } +no_aggregate: + { + GST_ERROR ("client %p: no aggregate path %s", client, path); + send_generic_response (client, + GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx); + g_free (path); + return FALSE; + } +invalid_state: + { + GST_ERROR ("client %p: not PLAYING or READY", client); + send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, + ctx); + return FALSE; + } +unsuspend_failed: + { + GST_ERROR ("client %p: unsuspend failed", client); + send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx); + return FALSE; + } +} + +static void +do_keepalive (GstRTSPSession * session) +{ + GST_INFO ("keep session %p alive", session); + gst_rtsp_session_touch (session); +} + +/* parse @transport and return a valid transport in @tr. only transports + * supported by @stream are returned. Returns FALSE if no valid transport + * was found. */ +static gboolean +parse_transport (const char *transport, GstRTSPStream * stream, + GstRTSPTransport * tr) +{ + gint i; + gboolean res; + gchar **transports; + + res = FALSE; + gst_rtsp_transport_init (tr); + + GST_DEBUG ("parsing transports %s", transport); + + transports = g_strsplit (transport, ",", 0); + + /* loop through the transports, try to parse */ + for (i = 0; transports[i]; i++) { + res = gst_rtsp_transport_parse (transports[i], tr); + if (res != GST_RTSP_OK) { + /* no valid transport, search some more */ + GST_WARNING ("could not parse transport %s", transports[i]); + goto next; + } + + /* we have a transport, see if it's supported */ + if (!gst_rtsp_stream_is_transport_supported (stream, tr)) { + GST_WARNING ("unsupported transport %s", transports[i]); + goto next; + } + + /* we have a valid transport */ + GST_INFO ("found valid transport %s", transports[i]); + res = TRUE; + break; + + next: + gst_rtsp_transport_init (tr); + } + g_strfreev (transports); + + return res; +} + +static gboolean +default_configure_client_media (GstRTSPClient * client, GstRTSPMedia * media, + GstRTSPStream * stream, GstRTSPContext * ctx) +{ + GstRTSPMessage *request = ctx->request; + gchar *blocksize_str; + + if (gst_rtsp_message_get_header (request, GST_RTSP_HDR_BLOCKSIZE, + &blocksize_str, 0) == GST_RTSP_OK) { + guint64 blocksize; + gchar *end; + + blocksize = g_ascii_strtoull (blocksize_str, &end, 10); + if (end == blocksize_str) + goto parse_failed; + + /* we don't want to change the mtu when this media + * can be shared because it impacts other clients */ + if (gst_rtsp_media_is_shared (media)) + goto done; + + if (blocksize > G_MAXUINT) + blocksize = G_MAXUINT; + + gst_rtsp_stream_set_mtu (stream, blocksize); + } +done: + return TRUE; + + /* ERRORS */ +parse_failed: + { + GST_ERROR_OBJECT (client, "failed to parse blocksize"); + send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx); + return FALSE; + } +} + +static gboolean +default_configure_client_transport (GstRTSPClient * client, + GstRTSPContext * ctx, GstRTSPTransport * ct) +{ + GstRTSPClientPrivate *priv = client->priv; + + /* we have a valid transport now, set the destination of the client. */ + if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) { + gboolean use_client_settings; + + use_client_settings = + gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS); + + if (ct->destination && use_client_settings) { + GstRTSPAddress *addr; + + addr = gst_rtsp_stream_reserve_address (ctx->stream, ct->destination, + ct->port.min, ct->port.max - ct->port.min + 1, ct->ttl); + + if (addr == NULL) + goto no_address; + + gst_rtsp_address_free (addr); + } else { + GstRTSPAddress *addr; + GSocketFamily family; + + family = priv->is_ipv6 ? G_SOCKET_FAMILY_IPV6 : G_SOCKET_FAMILY_IPV4; + + addr = gst_rtsp_stream_get_multicast_address (ctx->stream, family); + if (addr == NULL) + goto no_address; + + g_free (ct->destination); + ct->destination = g_strdup (addr->address); + ct->port.min = addr->port; + ct->port.max = addr->port + addr->n_ports - 1; + ct->ttl = addr->ttl; + + gst_rtsp_address_free (addr); + } + } else { + GstRTSPUrl *url; + + url = gst_rtsp_connection_get_url (priv->connection); + g_free (ct->destination); + ct->destination = g_strdup (url->host); + + if (ct->lower_transport & GST_RTSP_LOWER_TRANS_TCP) { + GSocket *sock; + GSocketAddress *addr; + + sock = gst_rtsp_connection_get_read_socket (priv->connection); + if ((addr = g_socket_get_remote_address (sock, NULL))) { + /* our read port is the sender port of client */ + ct->client_port.min = + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); + g_object_unref (addr); + } + if ((addr = g_socket_get_local_address (sock, NULL))) { + ct->server_port.max = + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); + g_object_unref (addr); + } + sock = gst_rtsp_connection_get_write_socket (priv->connection); + if ((addr = g_socket_get_remote_address (sock, NULL))) { + /* our write port is the receiver port of client */ + ct->client_port.max = + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); + g_object_unref (addr); + } + if ((addr = g_socket_get_local_address (sock, NULL))) { + ct->server_port.min = + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); + g_object_unref (addr); + } + /* check if the client selected channels for TCP */ + if (ct->interleaved.min == -1 || ct->interleaved.max == -1) { + gst_rtsp_session_media_alloc_channels (ctx->sessmedia, + &ct->interleaved); + } + } + } + return TRUE; + + /* ERRORS */ +no_address: + { + GST_ERROR_OBJECT (client, "failed to acquire address for stream"); + return FALSE; + } +} + +static GstRTSPTransport * +make_server_transport (GstRTSPClient * client, GstRTSPContext * ctx, + GstRTSPTransport * ct) +{ + GstRTSPTransport *st; + GInetAddress *addr; + GSocketFamily family; + + /* prepare the server transport */ + gst_rtsp_transport_new (&st); + + st->trans = ct->trans; + st->profile = ct->profile; + st->lower_transport = ct->lower_transport; + + addr = g_inet_address_new_from_string (ct->destination); + + if (!addr) { + GST_ERROR ("failed to get inet addr from client destination"); + family = G_SOCKET_FAMILY_IPV4; + } else { + family = g_inet_address_get_family (addr); + g_object_unref (addr); + addr = NULL; + } + + switch (st->lower_transport) { + case GST_RTSP_LOWER_TRANS_UDP: + st->client_port = ct->client_port; + gst_rtsp_stream_get_server_port (ctx->stream, &st->server_port, family); + break; + case GST_RTSP_LOWER_TRANS_UDP_MCAST: + st->port = ct->port; + st->destination = g_strdup (ct->destination); + st->ttl = ct->ttl; + break; + case GST_RTSP_LOWER_TRANS_TCP: + st->interleaved = ct->interleaved; + st->client_port = ct->client_port; + st->server_port = ct->server_port; + default: + break; + } + + gst_rtsp_stream_get_ssrc (ctx->stream, &st->ssrc); + + return st; +} + +#define AES_128_KEY_LEN 16 +#define AES_256_KEY_LEN 32 + +#define HMAC_32_KEY_LEN 4 +#define HMAC_80_KEY_LEN 10 + +static gboolean +mikey_apply_policy (GstCaps * caps, GstMIKEYMessage * msg, guint8 policy) +{ + const gchar *srtp_cipher; + const gchar *srtp_auth; + const GstMIKEYPayload *sp; + guint i; + + /* loop over Security policy until we find one containing policy */ + for (i = 0;; i++) { + if ((sp = gst_mikey_message_find_payload (msg, GST_MIKEY_PT_SP, i)) == NULL) + break; + + if (((GstMIKEYPayloadSP *) sp)->policy == policy) + break; + } + + /* the default ciphers */ + srtp_cipher = "aes-128-icm"; + srtp_auth = "hmac-sha1-80"; + + /* now override the defaults with what is in the Security Policy */ + if (sp != NULL) { + guint len; + + /* collect all the params and go over them */ + len = gst_mikey_payload_sp_get_n_params (sp); + for (i = 0; i < len; i++) { + const GstMIKEYPayloadSPParam *param = + gst_mikey_payload_sp_get_param (sp, i); + + switch (param->type) { + case GST_MIKEY_SP_SRTP_ENC_ALG: + switch (param->val[0]) { + case 0: + srtp_cipher = "null"; + break; + case 2: + case 1: + srtp_cipher = "aes-128-icm"; + break; + default: + break; + } + break; + case GST_MIKEY_SP_SRTP_ENC_KEY_LEN: + switch (param->val[0]) { + case AES_128_KEY_LEN: + srtp_cipher = "aes-128-icm"; + break; + case AES_256_KEY_LEN: + srtp_cipher = "aes-256-icm"; + break; + default: + break; + } + break; + case GST_MIKEY_SP_SRTP_AUTH_ALG: + switch (param->val[0]) { + case 0: + srtp_auth = "null"; + break; + case 2: + case 1: + srtp_auth = "hmac-sha1-80"; + break; + default: + break; + } + break; + case GST_MIKEY_SP_SRTP_AUTH_KEY_LEN: + switch (param->val[0]) { + case HMAC_32_KEY_LEN: + srtp_auth = "hmac-sha1-32"; + break; + case HMAC_80_KEY_LEN: + srtp_auth = "hmac-sha1-80"; + break; + default: + break; + } + break; + case GST_MIKEY_SP_SRTP_SRTP_ENC: + break; + case GST_MIKEY_SP_SRTP_SRTCP_ENC: + break; + default: + break; + } + } + } + /* now configure the SRTP parameters */ + gst_caps_set_simple (caps, + "srtp-cipher", G_TYPE_STRING, srtp_cipher, + "srtp-auth", G_TYPE_STRING, srtp_auth, + "srtcp-cipher", G_TYPE_STRING, srtp_cipher, + "srtcp-auth", G_TYPE_STRING, srtp_auth, NULL); + + return TRUE; +} + +static gboolean +handle_mikey_data (GstRTSPClient * client, GstRTSPContext * ctx, + guint8 * data, gsize size) +{ + GstMIKEYMessage *msg; + guint i, n_cs; + GstCaps *caps = NULL; + GstMIKEYPayloadKEMAC *kemac; + const GstMIKEYPayloadKeyData *pkd; + GstBuffer *key; + + /* the MIKEY message contains a CSB or crypto session bundle. It is a + * set of Crypto Sessions protected with the same master key. + * In the context of SRTP, an RTP and its RTCP stream is part of a + * crypto session */ + if ((msg = gst_mikey_message_new_from_data (data, size, NULL, NULL)) == NULL) + goto parse_failed; + + /* we can only handle SRTP crypto sessions for now */ + if (msg->map_type != GST_MIKEY_MAP_TYPE_SRTP) + goto invalid_map_type; + + /* get the number of crypto sessions. This maps SSRC to its + * security parameters */ + n_cs = gst_mikey_message_get_n_cs (msg); + if (n_cs == 0) + goto no_crypto_sessions; + + /* we also need keys */ + if (!(kemac = (GstMIKEYPayloadKEMAC *) gst_mikey_message_find_payload + (msg, GST_MIKEY_PT_KEMAC, 0))) + goto no_keys; + + /* we don't support encrypted keys */ + if (kemac->enc_alg != GST_MIKEY_ENC_NULL + || kemac->mac_alg != GST_MIKEY_MAC_NULL) + goto unsupported_encryption; + + /* get Key data sub-payload */ + pkd = (const GstMIKEYPayloadKeyData *) + gst_mikey_payload_kemac_get_sub (&kemac->pt, 0); + + key = + gst_buffer_new_wrapped (g_memdup (pkd->key_data, pkd->key_len), + pkd->key_len); + + /* go over all crypto sessions and create the security policy for each + * SSRC */ + for (i = 0; i < n_cs; i++) { + const GstMIKEYMapSRTP *map = gst_mikey_message_get_cs_srtp (msg, i); + + caps = gst_caps_new_simple ("application/x-srtp", + "ssrc", G_TYPE_UINT, map->ssrc, + "roc", G_TYPE_UINT, map->roc, "srtp-key", GST_TYPE_BUFFER, key, NULL); + mikey_apply_policy (caps, msg, map->policy); + + gst_rtsp_stream_update_crypto (ctx->stream, map->ssrc, caps); + gst_caps_unref (caps); + } + gst_mikey_message_unref (msg); + gst_buffer_unref (key); + + return TRUE; + + /* ERRORS */ +parse_failed: + { + GST_DEBUG_OBJECT (client, "failed to parse MIKEY message"); + return FALSE; + } +invalid_map_type: + { + GST_DEBUG_OBJECT (client, "invalid map type %d", msg->map_type); + goto cleanup_message; + } +no_crypto_sessions: + { + GST_DEBUG_OBJECT (client, "no crypto sessions"); + goto cleanup_message; + } +no_keys: + { + GST_DEBUG_OBJECT (client, "no keys found"); + goto cleanup_message; + } +unsupported_encryption: + { + GST_DEBUG_OBJECT (client, "unsupported key encryption"); + goto cleanup_message; + } +cleanup_message: + { + gst_mikey_message_unref (msg); + return FALSE; + } +} + +#define IS_STRIP_CHAR(c) (g_ascii_isspace ((guchar)(c)) || ((c) == '\"')) + +static void +strip_chars (gchar * str) +{ + gchar *s; + gsize len; + + len = strlen (str); + while (len--) { + if (!IS_STRIP_CHAR (str[len])) + break; + str[len] = '\0'; + } + for (s = str; *s && IS_STRIP_CHAR (*s); s++); + memmove (str, s, len + 1); +} + +/* KeyMgmt = "KeyMgmt" ":" key-mgmt-spec 0*("," key-mgmt-spec) + * key-mgmt-spec = "prot" "=" KMPID ";" ["uri" "=" %x22 URI %x22 ";"] + */ +static gboolean +handle_keymgmt (GstRTSPClient * client, GstRTSPContext * ctx, gchar * keymgmt) +{ + gchar **specs; + gint i, j; + + specs = g_strsplit (keymgmt, ",", 0); + for (i = 0; specs[i]; i++) { + gchar **split; + + split = g_strsplit (specs[i], ";", 0); + for (j = 0; split[j]; j++) { + g_strstrip (split[j]); + if (g_str_has_prefix (split[j], "prot=")) { + g_strstrip (split[j] + 5); + if (!g_str_equal (split[j] + 5, "mikey")) + break; + GST_DEBUG ("found mikey"); + } else if (g_str_has_prefix (split[j], "uri=")) { + strip_chars (split[j] + 4); + GST_DEBUG ("found uri '%s'", split[j] + 4); + } else if (g_str_has_prefix (split[j], "data=")) { + guchar *data; + gsize size; + strip_chars (split[j] + 5); + GST_DEBUG ("found data '%s'", split[j] + 5); + data = g_base64_decode_inplace (split[j] + 5, &size); + handle_mikey_data (client, ctx, data, size); + } + } + g_strfreev (split); + } + g_strfreev (specs); + return TRUE; +} + +static gboolean +handle_setup_request (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPClientPrivate *priv = client->priv; + GstRTSPResult res; + GstRTSPUrl *uri; + gchar *transport, *keymgmt; + GstRTSPTransport *ct, *st; + GstRTSPStatusCode code; + GstRTSPSession *session; + GstRTSPStreamTransport *trans; + gchar *trans_str; + GstRTSPSessionMedia *sessmedia; + GstRTSPMedia *media; + GstRTSPStream *stream; + GstRTSPState rtspstate; + GstRTSPClientClass *klass; + gchar *path, *control; + gint matched; + gboolean new_session = FALSE; + + if (!ctx->uri) + goto no_uri; + + uri = ctx->uri; + klass = GST_RTSP_CLIENT_GET_CLASS (client); + path = klass->make_path_from_uri (client, uri); + + /* parse the transport */ + res = + gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_TRANSPORT, + &transport, 0); + if (res != GST_RTSP_OK) + goto no_transport; + + /* we create the session after parsing stuff so that we don't make + * a session for malformed requests */ + if (priv->session_pool == NULL) + goto no_pool; + + session = ctx->session; + + if (session) { + g_object_ref (session); + /* get a handle to the configuration of the media in the session, this can + * return NULL if this is a new url to manage in this session. */ + sessmedia = gst_rtsp_session_get_media (session, path, &matched); + } else { + /* we need a new media configuration in this session */ + sessmedia = NULL; + } + + /* we have no session media, find one and manage it */ + if (sessmedia == NULL) { + /* get a handle to the configuration of the media in the session */ + media = find_media (client, ctx, path, &matched); + } else { + if ((media = gst_rtsp_session_media_get_media (sessmedia))) + g_object_ref (media); + else + goto media_not_found; + } + /* no media, not found then */ + if (media == NULL) + goto media_not_found_no_reply; + + /* FIXME-WFD : wfd url problem */ +#if 0 + if (path[matched] == '\0') + goto control_not_found; + + /* path is what matched. */ + path[matched] = '\0'; + /* control is remainder */ + control = &path[matched + 1]; +#else + control = g_strdup ("stream=0"); +#endif + + /* find the stream now using the control part */ + stream = gst_rtsp_media_find_stream (media, control); + if (stream == NULL) + goto stream_not_found; + + /* now we have a uri identifying a valid media and stream */ + ctx->stream = stream; + ctx->media = media; + + if (session == NULL) { + /* create a session if this fails we probably reached our session limit or + * something. */ + if (!(session = gst_rtsp_session_pool_create (priv->session_pool))) + goto service_unavailable; + + /* make sure this client is closed when the session is closed */ + client_watch_session (client, session); + + new_session = TRUE; + /* signal new session */ + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_NEW_SESSION], 0, + session); + + ctx->session = session; + } + + if (!klass->configure_client_media (client, media, stream, ctx)) + goto configure_media_failed_no_reply; + + gst_rtsp_transport_new (&ct); + + /* parse and find a usable supported transport */ + if (!parse_transport (transport, stream, ct)) + goto unsupported_transports; + + /* update the client transport */ + if (!klass->configure_client_transport (client, ctx, ct)) + goto unsupported_client_transport; + + /* parse the keymgmt */ + if (gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_KEYMGMT, + &keymgmt, 0) == GST_RTSP_OK) { + if (!handle_keymgmt (client, ctx, keymgmt)) + goto keymgmt_error; + } + + if (sessmedia == NULL) { + /* manage the media in our session now, if not done already */ + sessmedia = gst_rtsp_session_manage_media (session, path, media); + /* if we stil have no media, error */ + if (sessmedia == NULL) + goto sessmedia_unavailable; + } else { + g_object_unref (media); + } + + ctx->sessmedia = sessmedia; + + /* set in the session media transport */ + trans = gst_rtsp_session_media_set_transport (sessmedia, stream, ct); + + /* configure the url used to set this transport, this we will use when + * generating the response for the PLAY request */ + gst_rtsp_stream_transport_set_url (trans, uri); + + /* configure keepalive for this transport */ + gst_rtsp_stream_transport_set_keepalive (trans, + (GstRTSPKeepAliveFunc) do_keepalive, session, NULL); + + /* create and serialize the server transport */ + st = make_server_transport (client, ctx, ct); + trans_str = gst_rtsp_transport_as_text (st); + + /* FIXME-WFD : Temporarily force to set profile string */ + trans_str = g_strjoinv ("RTP/AVP/UDP", g_strsplit (trans_str, "RTP/AVP", -1)); + + gst_rtsp_transport_free (st); + + /* construct the response now */ + code = GST_RTSP_STS_OK; + gst_rtsp_message_init_response (ctx->response, code, + gst_rtsp_status_as_text (code), ctx->request); + + gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_TRANSPORT, + trans_str); + g_free (trans_str); + + send_message (client, ctx, ctx->response, FALSE); + + /* update the state */ + rtspstate = gst_rtsp_session_media_get_rtsp_state (sessmedia); + switch (rtspstate) { + case GST_RTSP_STATE_PLAYING: + case GST_RTSP_STATE_RECORDING: + case GST_RTSP_STATE_READY: + /* no state change */ + break; + default: + gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_READY); + break; + } + g_object_unref (session); + g_free (path); + + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_SETUP_REQUEST], 0, ctx); + + return TRUE; + + /* ERRORS */ +no_uri: + { + GST_ERROR ("client %p: no uri", client); + send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx); + return FALSE; + } +no_transport: + { + GST_ERROR ("client %p: no transport", client); + send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, ctx); + goto cleanup_path; + } +no_pool: + { + GST_ERROR ("client %p: no session pool configured", client); + send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx); + goto cleanup_path; + } +media_not_found_no_reply: + { + GST_ERROR ("client %p: media '%s' not found", client, path); + /* error reply is already sent */ + goto cleanup_path; + } +media_not_found: + { + GST_ERROR ("client %p: media '%s' not found", client, path); + send_generic_response (client, GST_RTSP_STS_NOT_FOUND, ctx); + goto cleanup_path; + } +#if 0 +control_not_found: + { + GST_ERROR ("client %p: no control in path '%s'", client, path); + send_generic_response (client, GST_RTSP_STS_NOT_FOUND, ctx); + g_object_unref (media); + goto cleanup_path; + } +#endif +stream_not_found: + { + GST_ERROR ("client %p: stream '%s' not found", client, control); + send_generic_response (client, GST_RTSP_STS_NOT_FOUND, ctx); + g_object_unref (media); + goto cleanup_path; + } +service_unavailable: + { + GST_ERROR ("client %p: can't create session", client); + send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx); + g_object_unref (media); + goto cleanup_path; + } +sessmedia_unavailable: + { + GST_ERROR ("client %p: can't create session media", client); + send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx); + g_object_unref (media); + goto cleanup_session; + } +configure_media_failed_no_reply: + { + GST_ERROR ("client %p: configure_media failed", client); + /* error reply is already sent */ + goto cleanup_session; + } +unsupported_transports: + { + GST_ERROR ("client %p: unsupported transports", client); + send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, ctx); + goto cleanup_transport; + } +unsupported_client_transport: + { + GST_ERROR ("client %p: unsupported client transport", client); + send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, ctx); + goto cleanup_transport; + } +keymgmt_error: + { + GST_ERROR ("client %p: keymgmt error", client); + send_generic_response (client, GST_RTSP_STS_KEY_MANAGEMENT_FAILURE, ctx); + goto cleanup_transport; + } + { + cleanup_transport: + gst_rtsp_transport_free (ct); + cleanup_session: + if (new_session) + gst_rtsp_session_pool_remove (priv->session_pool, session); + g_object_unref (session); + cleanup_path: + g_free (path); + return FALSE; + } +} + +static GstSDPMessage * +create_sdp (GstRTSPClient * client, GstRTSPMedia * media) +{ + GstRTSPClientPrivate *priv = client->priv; + GstSDPMessage *sdp; + GstSDPInfo info; + const gchar *proto; + + gst_sdp_message_new (&sdp); + + /* some standard things first */ + gst_sdp_message_set_version (sdp, "0"); + + if (priv->is_ipv6) + proto = "IP6"; + else + proto = "IP4"; + + gst_sdp_message_set_origin (sdp, "-", "1188340656180883", "1", "IN", proto, + priv->server_ip); + + gst_sdp_message_set_session_name (sdp, "Session streamed with GStreamer"); + gst_sdp_message_set_information (sdp, "rtsp-server"); + gst_sdp_message_add_time (sdp, "0", "0", NULL); + gst_sdp_message_add_attribute (sdp, "tool", "GStreamer"); + gst_sdp_message_add_attribute (sdp, "type", "broadcast"); + gst_sdp_message_add_attribute (sdp, "control", "*"); + + info.is_ipv6 = priv->is_ipv6; + info.server_ip = priv->server_ip; + + /* create an SDP for the media object */ + if (!gst_rtsp_media_setup_sdp (media, sdp, &info)) + goto no_sdp; + + return sdp; + + /* ERRORS */ +no_sdp: + { + GST_ERROR ("client %p: could not create SDP", client); + gst_sdp_message_free (sdp); + return NULL; + } +} + +/* for the describe we must generate an SDP */ +static gboolean +handle_describe_request (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPClientPrivate *priv = client->priv; + GstRTSPResult res; + GstSDPMessage *sdp; + guint i; + gchar *path, *str; + GstRTSPMedia *media; + GstRTSPClientClass *klass; + + klass = GST_RTSP_CLIENT_GET_CLASS (client); + + if (!ctx->uri) + goto no_uri; + + /* check what kind of format is accepted, we don't really do anything with it + * and always return SDP for now. */ + for (i = 0;; i++) { + gchar *accept; + + res = + gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_ACCEPT, + &accept, i); + if (res == GST_RTSP_ENOTIMPL) + break; + + if (g_ascii_strcasecmp (accept, "application/sdp") == 0) + break; + } + + if (!priv->mount_points) + goto no_mount_points; + + if (!(path = gst_rtsp_mount_points_make_path (priv->mount_points, ctx->uri))) + goto no_path; + + /* find the media object for the uri */ + if (!(media = find_media (client, ctx, path, NULL))) + goto no_media; + + /* create an SDP for the media object on this client */ + if (!(sdp = klass->create_sdp (client, media))) + goto no_sdp; + + /* we suspend after the describe */ + gst_rtsp_media_suspend (media); + g_object_unref (media); + + gst_rtsp_message_init_response (ctx->response, GST_RTSP_STS_OK, + gst_rtsp_status_as_text (GST_RTSP_STS_OK), ctx->request); + + gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_CONTENT_TYPE, + "application/sdp"); + + /* content base for some clients that might screw up creating the setup uri */ + str = make_base_url (client, ctx->uri, path); + g_free (path); + + GST_INFO ("adding content-base: %s", str); + gst_rtsp_message_take_header (ctx->response, GST_RTSP_HDR_CONTENT_BASE, str); + + /* add SDP to the response body */ + str = gst_sdp_message_as_text (sdp); + gst_rtsp_message_take_body (ctx->response, (guint8 *) str, strlen (str)); + gst_sdp_message_free (sdp); + + send_message (client, ctx, ctx->response, FALSE); + + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_DESCRIBE_REQUEST], + 0, ctx); + + return TRUE; + + /* ERRORS */ +no_uri: + { + GST_ERROR ("client %p: no uri", client); + send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx); + return FALSE; + } +no_mount_points: + { + GST_ERROR ("client %p: no mount points configured", client); + send_generic_response (client, GST_RTSP_STS_NOT_FOUND, ctx); + return FALSE; + } +no_path: + { + GST_ERROR ("client %p: can't find path for url", client); + send_generic_response (client, GST_RTSP_STS_NOT_FOUND, ctx); + return FALSE; + } +no_media: + { + GST_ERROR ("client %p: no media", client); + g_free (path); + /* error reply is already sent */ + return FALSE; + } +no_sdp: + { + GST_ERROR ("client %p: can't create SDP", client); + send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx); + g_free (path); + g_object_unref (media); + return FALSE; + } +} + +static gboolean +default_handle_options_request (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPMethod options; + gchar *str; + + options = GST_RTSP_DESCRIBE | + GST_RTSP_OPTIONS | + GST_RTSP_PAUSE | + GST_RTSP_PLAY | + GST_RTSP_SETUP | + GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN; + + str = gst_rtsp_options_as_text (options); + + gst_rtsp_message_init_response (ctx->response, GST_RTSP_STS_OK, + gst_rtsp_status_as_text (GST_RTSP_STS_OK), ctx->request); + + gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_PUBLIC, str); + g_free (str); + + send_message (client, ctx, ctx->response, FALSE); + + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_OPTIONS_REQUEST], + 0, ctx); + + return TRUE; +} + +/* remove duplicate and trailing '/' */ +static void +sanitize_uri (GstRTSPUrl * uri) +{ + gint i, len; + gchar *s, *d; + gboolean have_slash, prev_slash; + + s = d = uri->abspath; + len = strlen (uri->abspath); + + prev_slash = FALSE; + + for (i = 0; i < len; i++) { + have_slash = s[i] == '/'; + *d = s[i]; + if (!have_slash || !prev_slash) + d++; + prev_slash = have_slash; + } + len = d - uri->abspath; + /* don't remove the first slash if that's the only thing left */ + if (len > 1 && *(d - 1) == '/') + d--; + *d = '\0'; +} + +/* is called when the session is removed from its session pool. */ +static void +client_session_removed (GstRTSPSessionPool * pool, GstRTSPSession * session, + GstRTSPClient * client) +{ + GstRTSPClientPrivate *priv = client->priv; + + GST_INFO ("client %p: session %p removed", client, session); + + g_mutex_lock (&priv->lock); + client_unwatch_session (client, session, NULL); + g_mutex_unlock (&priv->lock); +} + +/* Returns TRUE if there are no Require headers, otherwise returns FALSE + * and also returns a newly-allocated string of (comma-separated) unsupported + * options in the unsupported_reqs variable . + * + * There may be multiple Require headers, but we must send one single + * Unsupported header with all the unsupported options as response. If + * an incoming Require header contained a comma-separated list of options + * GstRtspConnection will already have split that list up into multiple + * headers. + * + * TODO: allow the application to decide what features are supported + */ +static gboolean +check_request_requirements (GstRTSPMessage * msg, gchar ** unsupported_reqs) +{ + GstRTSPResult res; + GPtrArray *arr = NULL; + gchar *reqs = NULL; + gint i; + + i = 0; + do { + res = gst_rtsp_message_get_header (msg, GST_RTSP_HDR_REQUIRE, &reqs, i++); + + if (res == GST_RTSP_ENOTIMPL) + break; + + if (arr == NULL) + arr = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); + + g_ptr_array_add (arr, g_strdup (reqs)); + } + while (TRUE); + + /* if we don't have any Require headers at all, all is fine */ + if (i == 1) + return TRUE; + + /* otherwise we've now processed at all the Require headers */ + g_ptr_array_add (arr, NULL); + + /* for now we don't commit to supporting anything, so will just report + * all of the required options as unsupported */ + *unsupported_reqs = g_strjoinv (", ", (gchar **) arr->pdata); + + g_ptr_array_unref (arr); + return FALSE; +} + +static void +handle_request (GstRTSPClient * client, GstRTSPMessage * request) +{ + GstRTSPClientPrivate *priv = client->priv; + GstRTSPMethod method; + const gchar *uristr; + GstRTSPUrl *uri = NULL; + GstRTSPVersion version; + GstRTSPResult res; + GstRTSPSession *session = NULL; + GstRTSPContext sctx = { NULL }, *ctx; + GstRTSPMessage response = { 0 }; + gchar *unsupported_reqs = NULL; + gchar *sessid; + GstRTSPClientClass *klass; + + klass = GST_RTSP_CLIENT_GET_CLASS (client); + + if (!(ctx = gst_rtsp_context_get_current ())) { + ctx = &sctx; + ctx->auth = priv->auth; + gst_rtsp_context_push_current (ctx); + } + + ctx->conn = priv->connection; + ctx->client = client; + ctx->request = request; + ctx->response = &response; + + if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) { + gst_rtsp_message_dump (request); + } + + gst_rtsp_message_parse_request (request, &method, &uristr, &version); + + GST_INFO ("client %p: received a request %s %s %s", client, + gst_rtsp_method_as_text (method), uristr, + gst_rtsp_version_as_text (version)); + + /* we can only handle 1.0 requests */ + if (version != GST_RTSP_VERSION_1_0) + goto not_supported; + + ctx->method = method; + + /* we always try to parse the url first */ + if (strcmp (uristr, "*") == 0) { + /* special case where we have * as uri, keep uri = NULL */ + } else if (gst_rtsp_url_parse (uristr, &uri) != GST_RTSP_OK) { + /* check if the uristr is an absolute path <=> scheme and host information + * is missing */ + gchar *scheme; + + scheme = g_uri_parse_scheme (uristr); + if (scheme == NULL && g_str_has_prefix (uristr, "/")) { + gchar *absolute_uristr = NULL; + + GST_WARNING_OBJECT (client, "request doesn't contain absolute url"); + if (priv->server_ip == NULL) { + GST_WARNING_OBJECT (client, "host information missing"); + goto bad_request; + } + + absolute_uristr = + g_strdup_printf ("rtsp://%s%s", priv->server_ip, uristr); + + GST_DEBUG_OBJECT (client, "absolute url: %s", absolute_uristr); + if (gst_rtsp_url_parse (absolute_uristr, &uri) != GST_RTSP_OK) { + g_free (absolute_uristr); + goto bad_request; + } + g_free (absolute_uristr); + } else { + g_free (scheme); + goto bad_request; + } + } + + /* get the session if there is any */ + res = gst_rtsp_message_get_header (request, GST_RTSP_HDR_SESSION, &sessid, 0); + if (res == GST_RTSP_OK) { + if (priv->session_pool == NULL) + goto no_pool; + + /* we had a session in the request, find it again */ + if (!(session = gst_rtsp_session_pool_find (priv->session_pool, sessid))) + goto session_not_found; + + /* we add the session to the client list of watched sessions. When a session + * disappears because it times out, we will be notified. If all sessions are + * gone, we will close the connection */ + client_watch_session (client, session); + } + + /* sanitize the uri */ + if (uri) + sanitize_uri (uri); + ctx->uri = uri; + ctx->session = session; + + if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_URL)) + goto not_authorized; + +#if 0 + /* FIXME-WFD : How does it handle this */ + /* handle any 'Require' headers */ + if (!check_request_requirements (ctx->request, &unsupported_reqs)) + goto unsupported_requirement; +#endif + + /* now see what is asked and dispatch to a dedicated handler */ + switch (method) { + case GST_RTSP_OPTIONS: + klass->handle_options_request (client, ctx); + break; + case GST_RTSP_DESCRIBE: + handle_describe_request (client, ctx); + break; + case GST_RTSP_SETUP: + handle_setup_request (client, ctx); + break; + case GST_RTSP_PLAY: + handle_play_request (client, ctx); + break; + case GST_RTSP_PAUSE: + handle_pause_request (client, ctx); + break; + case GST_RTSP_TEARDOWN: + handle_teardown_request (client, ctx); + break; + case GST_RTSP_SET_PARAMETER: + klass->handle_set_param_request (client, ctx); + break; + case GST_RTSP_GET_PARAMETER: + klass->handle_get_param_request (client, ctx); + break; + case GST_RTSP_ANNOUNCE: + case GST_RTSP_RECORD: + case GST_RTSP_REDIRECT: + goto not_implemented; + case GST_RTSP_INVALID: + default: + goto bad_request; + } + +done: + if (ctx == &sctx) + gst_rtsp_context_pop_current (ctx); + if (session) + g_object_unref (session); + if (uri) + gst_rtsp_url_free (uri); + return; + + /* ERRORS */ +not_supported: + { + GST_ERROR ("client %p: version %d not supported", client, version); + send_generic_response (client, GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED, + ctx); + goto done; + } +bad_request: + { + GST_ERROR ("client %p: bad request", client); + send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx); + goto done; + } +no_pool: + { + GST_ERROR ("client %p: no pool configured", client); + send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx); + goto done; + } +session_not_found: + { + GST_ERROR ("client %p: session not found", client); + send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx); + goto done; + } +not_authorized: + { + GST_ERROR ("client %p: not allowed", client); + /* error reply is already sent */ + goto done; + } +#if 0 +unsupported_requirement: + { + GST_ERROR ("client %p: Required option is not supported (%s)", client, + unsupported_reqs); + send_option_not_supported_response (client, ctx, unsupported_reqs); + g_free (unsupported_reqs); + goto done; + } +#endif +not_implemented: + { + GST_ERROR ("client %p: method %d not implemented", client, method); + send_generic_response (client, GST_RTSP_STS_NOT_IMPLEMENTED, ctx); + goto done; + } +} + + +static void +handle_response (GstRTSPClient * client, GstRTSPMessage * response) +{ + GstRTSPClientPrivate *priv = client->priv; + GstRTSPResult res; + GstRTSPSession *session = NULL; + GstRTSPContext sctx = { NULL }, *ctx; + gchar *sessid; + + if (!(ctx = gst_rtsp_context_get_current ())) { + ctx = &sctx; + ctx->auth = priv->auth; + gst_rtsp_context_push_current (ctx); + } + + ctx->conn = priv->connection; + ctx->client = client; + ctx->request = NULL; + ctx->uri = NULL; + ctx->method = GST_RTSP_INVALID; + ctx->response = response; + + if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) { + gst_rtsp_message_dump (response); + } + + GST_INFO ("client %p: received a response", client); + + /* get the session if there is any */ + res = + gst_rtsp_message_get_header (response, GST_RTSP_HDR_SESSION, &sessid, 0); + if (res == GST_RTSP_OK) { + if (priv->session_pool == NULL) + goto no_pool; + + /* we had a session in the request, find it again */ + if (!(session = gst_rtsp_session_pool_find (priv->session_pool, sessid))) + goto session_not_found; + + /* we add the session to the client list of watched sessions. When a session + * disappears because it times out, we will be notified. If all sessions are + * gone, we will close the connection */ + client_watch_session (client, session); + } + + ctx->session = session; + + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_HANDLE_RESPONSE], + 0, ctx); + +done: + if (ctx == &sctx) + gst_rtsp_context_pop_current (ctx); + if (session) + g_object_unref (session); + return; + +no_pool: + { + GST_ERROR ("client %p: no pool configured", client); + goto done; + } +session_not_found: + { + GST_ERROR ("client %p: session not found", client); + goto done; + } +} + +static void +handle_data (GstRTSPClient * client, GstRTSPMessage * message) +{ + GstRTSPClientPrivate *priv = client->priv; + GstRTSPResult res; + guint8 channel; + GList *walk; + guint8 *data; + guint size; + GstBuffer *buffer; + gboolean handled; + + /* find the stream for this message */ + res = gst_rtsp_message_parse_data (message, &channel); + if (res != GST_RTSP_OK) + return; + + gst_rtsp_message_steal_body (message, &data, &size); + + buffer = gst_buffer_new_wrapped (data, size); + + handled = FALSE; + for (walk = priv->transports; walk; walk = g_list_next (walk)) { + GstRTSPStreamTransport *trans; + GstRTSPStream *stream; + const GstRTSPTransport *tr; + + trans = walk->data; + + tr = gst_rtsp_stream_transport_get_transport (trans); + stream = gst_rtsp_stream_transport_get_stream (trans); + + /* check for TCP transport */ + if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) { + /* dispatch to the stream based on the channel number */ + if (tr->interleaved.min == channel) { + gst_rtsp_stream_recv_rtp (stream, buffer); + handled = TRUE; + break; + } else if (tr->interleaved.max == channel) { + gst_rtsp_stream_recv_rtcp (stream, buffer); + handled = TRUE; + break; + } + } + } + if (!handled) + gst_buffer_unref (buffer); +} + +/** + * gst_rtsp_client_set_session_pool: + * @client: a #GstRTSPClient + * @pool: (transfer none): a #GstRTSPSessionPool + * + * Set @pool as the sessionpool for @client which it will use to find + * or allocate sessions. the sessionpool is usually inherited from the server + * that created the client but can be overridden later. + */ +void +gst_rtsp_client_set_session_pool (GstRTSPClient * client, + GstRTSPSessionPool * pool) +{ + GstRTSPSessionPool *old; + GstRTSPClientPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_CLIENT (client)); + + priv = client->priv; + + if (pool) + g_object_ref (pool); + + g_mutex_lock (&priv->lock); + old = priv->session_pool; + priv->session_pool = pool; + + if (priv->session_removed_id) { + g_signal_handler_disconnect (old, priv->session_removed_id); + priv->session_removed_id = 0; + } + g_mutex_unlock (&priv->lock); + + /* FIXME, should remove all sessions from the old pool for this client */ + if (old) + g_object_unref (old); +} + +/** + * gst_rtsp_client_get_session_pool: + * @client: a #GstRTSPClient + * + * Get the #GstRTSPSessionPool object that @client uses to manage its sessions. + * + * Returns: (transfer full): a #GstRTSPSessionPool, unref after usage. + */ +GstRTSPSessionPool * +gst_rtsp_client_get_session_pool (GstRTSPClient * client) +{ + GstRTSPClientPrivate *priv; + GstRTSPSessionPool *result; + + g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL); + + priv = client->priv; + + g_mutex_lock (&priv->lock); + if ((result = priv->session_pool)) + g_object_ref (result); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_client_set_mount_points: + * @client: a #GstRTSPClient + * @mounts: (transfer none): a #GstRTSPMountPoints + * + * Set @mounts as the mount points for @client which it will use to map urls + * to media streams. These mount points are usually inherited from the server that + * created the client but can be overriden later. + */ +void +gst_rtsp_client_set_mount_points (GstRTSPClient * client, + GstRTSPMountPoints * mounts) +{ + GstRTSPClientPrivate *priv; + GstRTSPMountPoints *old; + + g_return_if_fail (GST_IS_RTSP_CLIENT (client)); + + priv = client->priv; + + if (mounts) + g_object_ref (mounts); + + g_mutex_lock (&priv->lock); + old = priv->mount_points; + priv->mount_points = mounts; + g_mutex_unlock (&priv->lock); + + if (old) + g_object_unref (old); +} + +/** + * gst_rtsp_client_get_mount_points: + * @client: a #GstRTSPClient + * + * Get the #GstRTSPMountPoints object that @client uses to manage its sessions. + * + * Returns: (transfer full): a #GstRTSPMountPoints, unref after usage. + */ +GstRTSPMountPoints * +gst_rtsp_client_get_mount_points (GstRTSPClient * client) +{ + GstRTSPClientPrivate *priv; + GstRTSPMountPoints *result; + + g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL); + + priv = client->priv; + + g_mutex_lock (&priv->lock); + if ((result = priv->mount_points)) + g_object_ref (result); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_client_set_auth: + * @client: a #GstRTSPClient + * @auth: (transfer none): a #GstRTSPAuth + * + * configure @auth to be used as the authentication manager of @client. + */ +void +gst_rtsp_client_set_auth (GstRTSPClient * client, GstRTSPAuth * auth) +{ + GstRTSPClientPrivate *priv; + GstRTSPAuth *old; + + g_return_if_fail (GST_IS_RTSP_CLIENT (client)); + + priv = client->priv; + + if (auth) + g_object_ref (auth); + + g_mutex_lock (&priv->lock); + old = priv->auth; + priv->auth = auth; + g_mutex_unlock (&priv->lock); + + if (old) + g_object_unref (old); +} + + +/** + * gst_rtsp_client_get_auth: + * @client: a #GstRTSPClient + * + * Get the #GstRTSPAuth used as the authentication manager of @client. + * + * Returns: (transfer full): the #GstRTSPAuth of @client. g_object_unref() after + * usage. + */ +GstRTSPAuth * +gst_rtsp_client_get_auth (GstRTSPClient * client) +{ + GstRTSPClientPrivate *priv; + GstRTSPAuth *result; + + g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL); + + priv = client->priv; + + g_mutex_lock (&priv->lock); + if ((result = priv->auth)) + g_object_ref (result); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_client_set_thread_pool: + * @client: a #GstRTSPClient + * @pool: (transfer none): a #GstRTSPThreadPool + * + * configure @pool to be used as the thread pool of @client. + */ +void +gst_rtsp_client_set_thread_pool (GstRTSPClient * client, + GstRTSPThreadPool * pool) +{ + GstRTSPClientPrivate *priv; + GstRTSPThreadPool *old; + + g_return_if_fail (GST_IS_RTSP_CLIENT (client)); + + priv = client->priv; + + if (pool) + g_object_ref (pool); + + g_mutex_lock (&priv->lock); + old = priv->thread_pool; + priv->thread_pool = pool; + g_mutex_unlock (&priv->lock); + + if (old) + g_object_unref (old); +} + +/** + * gst_rtsp_client_get_thread_pool: + * @client: a #GstRTSPClient + * + * Get the #GstRTSPThreadPool used as the thread pool of @client. + * + * Returns: (transfer full): the #GstRTSPThreadPool of @client. g_object_unref() after + * usage. + */ +GstRTSPThreadPool * +gst_rtsp_client_get_thread_pool (GstRTSPClient * client) +{ + GstRTSPClientPrivate *priv; + GstRTSPThreadPool *result; + + g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL); + + priv = client->priv; + + g_mutex_lock (&priv->lock); + if ((result = priv->thread_pool)) + g_object_ref (result); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_client_set_connection: + * @client: a #GstRTSPClient + * @conn: (transfer full): a #GstRTSPConnection + * + * Set the #GstRTSPConnection of @client. This function takes ownership of + * @conn. + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_client_set_connection (GstRTSPClient * client, + GstRTSPConnection * conn) +{ + GstRTSPClientPrivate *priv; + GSocket *read_socket; + GSocketAddress *address; + GstRTSPUrl *url; + GError *error = NULL; + + g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), FALSE); + g_return_val_if_fail (conn != NULL, FALSE); + + priv = client->priv; + + read_socket = gst_rtsp_connection_get_read_socket (conn); + + if (!(address = g_socket_get_local_address (read_socket, &error))) + goto no_address; + + g_free (priv->server_ip); + /* keep the original ip that the client connected to */ + if (G_IS_INET_SOCKET_ADDRESS (address)) { + GInetAddress *iaddr; + + iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address)); + + /* socket might be ipv6 but adress still ipv4 */ + priv->is_ipv6 = g_inet_address_get_family (iaddr) == G_SOCKET_FAMILY_IPV6; + priv->server_ip = g_inet_address_to_string (iaddr); + g_object_unref (address); + } else { + priv->is_ipv6 = g_socket_get_family (read_socket) == G_SOCKET_FAMILY_IPV6; + priv->server_ip = g_strdup ("unknown"); + } + + GST_INFO ("client %p connected to server ip %s, ipv6 = %d", client, + priv->server_ip, priv->is_ipv6); + + url = gst_rtsp_connection_get_url (conn); + GST_INFO ("added new client %p ip %s:%d", client, url->host, url->port); + + priv->connection = conn; + + return TRUE; + + /* ERRORS */ +no_address: + { + GST_ERROR ("could not get local address %s", error->message); + g_error_free (error); + return FALSE; + } +} + +/** + * gst_rtsp_client_get_connection: + * @client: a #GstRTSPClient + * + * Get the #GstRTSPConnection of @client. + * + * Returns: (transfer none): the #GstRTSPConnection of @client. + * The connection object returned remains valid until the client is freed. + */ +GstRTSPConnection * +gst_rtsp_client_get_connection (GstRTSPClient * client) +{ + g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL); + + return client->priv->connection; +} + +/** + * gst_rtsp_client_set_send_func: + * @client: a #GstRTSPClient + * @func: (scope notified): a #GstRTSPClientSendFunc + * @user_data: (closure): user data passed to @func + * @notify: (allow-none): called when @user_data is no longer in use + * + * Set @func as the callback that will be called when a new message needs to be + * sent to the client. @user_data is passed to @func and @notify is called when + * @user_data is no longer in use. + * + * By default, the client will send the messages on the #GstRTSPConnection that + * was configured with gst_rtsp_client_attach() was called. + */ +void +gst_rtsp_client_set_send_func (GstRTSPClient * client, + GstRTSPClientSendFunc func, gpointer user_data, GDestroyNotify notify) +{ + GstRTSPClientPrivate *priv; + GDestroyNotify old_notify; + gpointer old_data; + + g_return_if_fail (GST_IS_RTSP_CLIENT (client)); + + priv = client->priv; + + g_mutex_lock (&priv->send_lock); + priv->send_func = func; + old_notify = priv->send_notify; + old_data = priv->send_data; + priv->send_notify = notify; + priv->send_data = user_data; + g_mutex_unlock (&priv->send_lock); + + if (old_notify) + old_notify (old_data); +} + +/** + * gst_rtsp_client_handle_message: + * @client: a #GstRTSPClient + * @message: (transfer none): an #GstRTSPMessage + * + * Let the client handle @message. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_client_handle_message (GstRTSPClient * client, + GstRTSPMessage * message) +{ + g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), GST_RTSP_EINVAL); + g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL); + + switch (message->type) { + case GST_RTSP_MESSAGE_REQUEST: + handle_request (client, message); + break; + case GST_RTSP_MESSAGE_RESPONSE: + handle_response (client, message); + break; + case GST_RTSP_MESSAGE_DATA: + handle_data (client, message); + break; + default: + break; + } + return GST_RTSP_OK; +} + +/** + * gst_rtsp_client_send_message: + * @client: a #GstRTSPClient + * @session: (allow-none) (transfer none): a #GstRTSPSession to send + * the message to or %NULL + * @message: (transfer none): The #GstRTSPMessage to send + * + * Send a message message to the remote end. @message must be a + * #GST_RTSP_MESSAGE_REQUEST or a #GST_RTSP_MESSAGE_RESPONSE. + */ +GstRTSPResult +gst_rtsp_client_send_message (GstRTSPClient * client, GstRTSPSession * session, + GstRTSPMessage * message) +{ + GstRTSPContext sctx = { NULL } + , *ctx; + GstRTSPClientPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), GST_RTSP_EINVAL); + g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (message->type == GST_RTSP_MESSAGE_REQUEST || + message->type == GST_RTSP_MESSAGE_RESPONSE, GST_RTSP_EINVAL); + + priv = client->priv; + + if (!(ctx = gst_rtsp_context_get_current ())) { + ctx = &sctx; + ctx->auth = priv->auth; + gst_rtsp_context_push_current (ctx); + } + + ctx->conn = priv->connection; + ctx->client = client; + ctx->session = session; + + send_message (client, ctx, message, FALSE); + + if (ctx == &sctx) + gst_rtsp_context_pop_current (ctx); + + return GST_RTSP_OK; +} + +static GstRTSPResult +do_send_message (GstRTSPClient * client, GstRTSPMessage * message, + gboolean close, gpointer user_data) +{ + GstRTSPClientPrivate *priv = client->priv; + GstRTSPResult ret; + GTimeVal time; + + time.tv_sec = 1; + time.tv_usec = 0; + + do { + /* send the response and store the seq number so we can wait until it's + * written to the client to close the connection */ + ret = + gst_rtsp_watch_send_message (priv->watch, message, + close ? &priv->close_seq : NULL); + if (ret == GST_RTSP_OK) + break; + + if (ret != GST_RTSP_ENOMEM) + goto error; + + /* drop backlog */ + if (priv->drop_backlog) + break; + + /* queue was full, wait for more space */ + GST_DEBUG_OBJECT (client, "waiting for backlog"); + ret = gst_rtsp_watch_wait_backlog (priv->watch, &time); + GST_DEBUG_OBJECT (client, "Resend due to backlog full"); + } while (ret != GST_RTSP_EINTR); + + return ret; + + /* ERRORS */ +error: + { + GST_DEBUG_OBJECT (client, "got error %d", ret); + return ret; + } +} + +static GstRTSPResult +message_received (GstRTSPWatch * watch, GstRTSPMessage * message, + gpointer user_data) +{ + return gst_rtsp_client_handle_message (GST_RTSP_CLIENT (user_data), message); +} + +static GstRTSPResult +message_sent (GstRTSPWatch * watch, guint cseq, gpointer user_data) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + GstRTSPClientPrivate *priv = client->priv; + + if (priv->close_seq && priv->close_seq == cseq) { + GST_INFO ("client %p: send close message", client); + priv->close_seq = 0; + gst_rtsp_client_close (client); + } + + return GST_RTSP_OK; +} + +static GstRTSPResult +closed (GstRTSPWatch * watch, gpointer user_data) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + GstRTSPClientPrivate *priv = client->priv; + const gchar *tunnelid; + + GST_INFO ("client %p: connection closed", client); + + if ((tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection))) { + g_mutex_lock (&tunnels_lock); + /* remove from tunnelids */ + g_hash_table_remove (tunnels, tunnelid); + g_mutex_unlock (&tunnels_lock); + } + + gst_rtsp_watch_set_flushing (watch, TRUE); + g_mutex_lock (&priv->watch_lock); + gst_rtsp_client_set_send_func (client, NULL, NULL, NULL); + g_mutex_unlock (&priv->watch_lock); + + return GST_RTSP_OK; +} + +static GstRTSPResult +error (GstRTSPWatch * watch, GstRTSPResult result, gpointer user_data) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + gchar *str; + + str = gst_rtsp_strresult (result); + GST_INFO ("client %p: received an error %s", client, str); + g_free (str); + + return GST_RTSP_OK; +} + +static GstRTSPResult +error_full (GstRTSPWatch * watch, GstRTSPResult result, + GstRTSPMessage * message, guint id, gpointer user_data) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + gchar *str; + + str = gst_rtsp_strresult (result); + GST_INFO + ("client %p: error when handling message %p with id %d: %s", + client, message, id, str); + g_free (str); + + return GST_RTSP_OK; +} + +static gboolean +remember_tunnel (GstRTSPClient * client) +{ + GstRTSPClientPrivate *priv = client->priv; + const gchar *tunnelid; + + /* store client in the pending tunnels */ + tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection); + if (tunnelid == NULL) + goto no_tunnelid; + + GST_INFO ("client %p: inserting tunnel session %s", client, tunnelid); + + /* we can't have two clients connecting with the same tunnelid */ + g_mutex_lock (&tunnels_lock); + if (g_hash_table_lookup (tunnels, tunnelid)) + goto tunnel_existed; + + g_hash_table_insert (tunnels, g_strdup (tunnelid), g_object_ref (client)); + g_mutex_unlock (&tunnels_lock); + + return TRUE; + + /* ERRORS */ +no_tunnelid: + { + GST_ERROR ("client %p: no tunnelid provided", client); + return FALSE; + } +tunnel_existed: + { + g_mutex_unlock (&tunnels_lock); + GST_ERROR ("client %p: tunnel session %s already existed", client, + tunnelid); + return FALSE; + } +} + +static GstRTSPResult +tunnel_lost (GstRTSPWatch * watch, gpointer user_data) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + GstRTSPClientPrivate *priv = client->priv; + + GST_WARNING ("client %p: tunnel lost (connection %p)", client, + priv->connection); + + /* ignore error, it'll only be a problem when the client does a POST again */ + remember_tunnel (client); + + return GST_RTSP_OK; +} + +static gboolean +handle_tunnel (GstRTSPClient * client) +{ + GstRTSPClientPrivate *priv = client->priv; + GstRTSPClient *oclient; + GstRTSPClientPrivate *opriv; + const gchar *tunnelid; + + tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection); + if (tunnelid == NULL) + goto no_tunnelid; + + /* check for previous tunnel */ + g_mutex_lock (&tunnels_lock); + oclient = g_hash_table_lookup (tunnels, tunnelid); + + if (oclient == NULL) { + /* no previous tunnel, remember tunnel */ + g_hash_table_insert (tunnels, g_strdup (tunnelid), g_object_ref (client)); + g_mutex_unlock (&tunnels_lock); + + GST_INFO ("client %p: no previous tunnel found, remembering tunnel (%p)", + client, priv->connection); + } else { + /* merge both tunnels into the first client */ + /* remove the old client from the table. ref before because removing it will + * remove the ref to it. */ + g_object_ref (oclient); + g_hash_table_remove (tunnels, tunnelid); + g_mutex_unlock (&tunnels_lock); + + opriv = oclient->priv; + + g_mutex_lock (&opriv->watch_lock); + if (opriv->watch == NULL) + goto tunnel_closed; + + GST_INFO ("client %p: found previous tunnel %p (old %p, new %p)", client, + oclient, opriv->connection, priv->connection); + + gst_rtsp_connection_do_tunnel (opriv->connection, priv->connection); + gst_rtsp_watch_reset (priv->watch); + gst_rtsp_watch_reset (opriv->watch); + g_mutex_unlock (&opriv->watch_lock); + g_object_unref (oclient); + + /* the old client owns the tunnel now, the new one will be freed */ + g_source_destroy ((GSource *) priv->watch); + priv->watch = NULL; + gst_rtsp_client_set_send_func (client, NULL, NULL, NULL); + } + + return TRUE; + + /* ERRORS */ +no_tunnelid: + { + GST_ERROR ("client %p: no tunnelid provided", client); + return FALSE; + } +tunnel_closed: + { + GST_ERROR ("client %p: tunnel session %s was closed", client, tunnelid); + g_mutex_unlock (&opriv->watch_lock); + g_object_unref (oclient); + return FALSE; + } +} + +static GstRTSPStatusCode +tunnel_get (GstRTSPWatch * watch, gpointer user_data) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + + GST_INFO ("client %p: tunnel get (connection %p)", client, + client->priv->connection); + + if (!handle_tunnel (client)) { + return GST_RTSP_STS_SERVICE_UNAVAILABLE; + } + + return GST_RTSP_STS_OK; +} + +static GstRTSPResult +tunnel_post (GstRTSPWatch * watch, gpointer user_data) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + + GST_INFO ("client %p: tunnel post (connection %p)", client, + client->priv->connection); + + if (!handle_tunnel (client)) { + return GST_RTSP_ERROR; + } + + return GST_RTSP_OK; +} + +static GstRTSPResult +tunnel_http_response (GstRTSPWatch * watch, GstRTSPMessage * request, + GstRTSPMessage * response, gpointer user_data) +{ + GstRTSPClientClass *klass; + + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + klass = GST_RTSP_CLIENT_GET_CLASS (client); + + if (klass->tunnel_http_response) { + klass->tunnel_http_response (client, request, response); + } + + return GST_RTSP_OK; +} + +static GstRTSPWatchFuncs watch_funcs = { + message_received, + message_sent, + closed, + error, + tunnel_get, + tunnel_post, + error_full, + tunnel_lost, + tunnel_http_response +}; + +static void +client_watch_notify (GstRTSPClient * client) +{ + GstRTSPClientPrivate *priv = client->priv; + + GST_INFO ("client %p: watch destroyed", client); + priv->watch = NULL; + g_main_context_unref (priv->watch_context); + priv->watch_context = NULL; + /* remove all sessions and so drop the extra client ref */ + gst_rtsp_client_session_filter (client, cleanup_session, NULL); + g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_CLOSED], 0, NULL); + g_object_unref (client); +} + +/** + * gst_rtsp_client_attach: + * @client: a #GstRTSPClient + * @context: (allow-none): a #GMainContext + * + * Attaches @client to @context. When the mainloop for @context is run, the + * client will be dispatched. When @context is %NULL, the default context will be + * used). + * + * This function should be called when the client properties and urls are fully + * configured and the client is ready to start. + * + * Returns: the ID (greater than 0) for the source within the GMainContext. + */ +guint +gst_rtsp_client_attach (GstRTSPClient * client, GMainContext * context) +{ + GstRTSPClientPrivate *priv; + guint res; + + g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), 0); + priv = client->priv; + g_return_val_if_fail (priv->connection != NULL, 0); + g_return_val_if_fail (priv->watch == NULL, 0); + + /* make sure noone will free the context before the watch is destroyed */ + priv->watch_context = g_main_context_ref (context); + + /* create watch for the connection and attach */ + priv->watch = gst_rtsp_watch_new (priv->connection, &watch_funcs, + g_object_ref (client), (GDestroyNotify) client_watch_notify); + gst_rtsp_client_set_send_func (client, do_send_message, priv->watch, + (GDestroyNotify) gst_rtsp_watch_unref); + + /* FIXME make this configurable. We don't want to do this yet because it will + * be superceeded by a cache object later */ + gst_rtsp_watch_set_send_backlog (priv->watch, 0, 100); + + GST_INFO ("client %p: attaching to context %p", client, context); + res = gst_rtsp_watch_attach (priv->watch, context); + + return res; +} + +/** + * gst_rtsp_client_session_filter: + * @client: a #GstRTSPClient + * @func: (scope call) (allow-none): a callback + * @user_data: user data passed to @func + * + * Call @func for each session managed by @client. The result value of @func + * determines what happens to the session. @func will be called with @client + * locked so no further actions on @client can be performed from @func. + * + * If @func returns #GST_RTSP_FILTER_REMOVE, the session will be removed from + * @client. + * + * If @func returns #GST_RTSP_FILTER_KEEP, the session will remain in @client. + * + * If @func returns #GST_RTSP_FILTER_REF, the session will remain in @client but + * will also be added with an additional ref to the result #GList of this + * function.. + * + * When @func is %NULL, #GST_RTSP_FILTER_REF will be assumed for each session. + * + * Returns: (element-type GstRTSPSession) (transfer full): a #GList with all + * sessions for which @func returned #GST_RTSP_FILTER_REF. After usage, each + * element in the #GList should be unreffed before the list is freed. + */ +GList * +gst_rtsp_client_session_filter (GstRTSPClient * client, + GstRTSPClientSessionFilterFunc func, gpointer user_data) +{ + GstRTSPClientPrivate *priv; + GList *result, *walk, *next; + GHashTable *visited; + guint cookie; + + g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL); + + priv = client->priv; + + result = NULL; + if (func) + visited = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL); + + g_mutex_lock (&priv->lock); +restart: + cookie = priv->sessions_cookie; + for (walk = priv->sessions; walk; walk = next) { + GstRTSPSession *sess = walk->data; + GstRTSPFilterResult res; + gboolean changed; + + next = g_list_next (walk); + + if (func) { + /* only visit each session once */ + if (g_hash_table_contains (visited, sess)) + continue; + + g_hash_table_add (visited, g_object_ref (sess)); + g_mutex_unlock (&priv->lock); + + res = func (client, sess, user_data); + + g_mutex_lock (&priv->lock); + } else + res = GST_RTSP_FILTER_REF; + + changed = (cookie != priv->sessions_cookie); + + switch (res) { + case GST_RTSP_FILTER_REMOVE: + /* stop watching the session and pretend it went away, if the list was + * changed, we can't use the current list position, try to see if we + * still have the session */ + client_unwatch_session (client, sess, changed ? NULL : walk); + cookie = priv->sessions_cookie; + break; + case GST_RTSP_FILTER_REF: + result = g_list_prepend (result, g_object_ref (sess)); + break; + case GST_RTSP_FILTER_KEEP: + default: + break; + } + if (changed) + goto restart; + } + g_mutex_unlock (&priv->lock); + + if (func) + g_hash_table_unref (visited); + + return result; +} diff --git a/gst/rtsp-server/rtsp-client.h b/gst/rtsp-server/rtsp-client.h new file mode 100644 index 0000000..2ddb82e --- /dev/null +++ b/gst/rtsp-server/rtsp-client.h @@ -0,0 +1,196 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include +#include + +#ifndef __GST_RTSP_CLIENT_H__ +#define __GST_RTSP_CLIENT_H__ + +G_BEGIN_DECLS + +typedef struct _GstRTSPClient GstRTSPClient; +typedef struct _GstRTSPClientClass GstRTSPClientClass; +typedef struct _GstRTSPClientPrivate GstRTSPClientPrivate; + +#include "rtsp-context.h" +#include "rtsp-mount-points.h" +#include "rtsp-sdp.h" +#include "rtsp-auth.h" + +#define GST_TYPE_RTSP_CLIENT (gst_rtsp_client_get_type ()) +#define GST_IS_RTSP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_CLIENT)) +#define GST_IS_RTSP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_CLIENT)) +#define GST_RTSP_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_CLIENT, GstRTSPClientClass)) +#define GST_RTSP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_CLIENT, GstRTSPClient)) +#define GST_RTSP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_CLIENT, GstRTSPClientClass)) +#define GST_RTSP_CLIENT_CAST(obj) ((GstRTSPClient*)(obj)) +#define GST_RTSP_CLIENT_CLASS_CAST(klass) ((GstRTSPClientClass*)(klass)) + +/** + * GstRTSPClientSendFunc: + * @client: a #GstRTSPClient + * @message: a #GstRTSPMessage + * @close: close the connection + * @user_data: user data when registering the callback + * + * This callback is called when @client wants to send @message. When @close is + * %TRUE, the connection should be closed when the message has been sent. + * + * Returns: %TRUE on success. + */ +typedef gboolean (*GstRTSPClientSendFunc) (GstRTSPClient *client, + GstRTSPMessage *message, + gboolean close, + gpointer user_data); + +/** + * GstRTSPClient: + * + * The client object represents the connection and its state with a client. + */ +struct _GstRTSPClient { + GObject parent; + + /*< private >*/ + GstRTSPClientPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPClientClass: + * @create_sdp: called when the SDP needs to be created for media. + * @configure_client_media: called when the stream in media needs to be configured. + * The default implementation will configure the blocksize on the payloader when + * spcified in the request headers. + * @configure_client_transport: called when the client transport needs to be + * configured. + * @params_set: set parameters. This function should also initialize the + * RTSP response(ctx->response) via a call to gst_rtsp_message_init_response() + * @params_get: get parameters. This function should also initialize the + * RTSP response(ctx->response) via a call to gst_rtsp_message_init_response() + * @tunnel_http_response: called when a response to the GET request is about to + * be sent for a tunneled connection. The response can be modified. Since 1.4 + * + * The client class structure. + */ +struct _GstRTSPClientClass { + GObjectClass parent_class; + + GstSDPMessage * (*create_sdp) (GstRTSPClient *client, GstRTSPMedia *media); + gboolean (*configure_client_media) (GstRTSPClient * client, + GstRTSPMedia * media, GstRTSPStream * stream, + GstRTSPContext * ctx); + gboolean (*configure_client_transport) (GstRTSPClient * client, + GstRTSPContext * ctx, + GstRTSPTransport * ct); + GstRTSPResult (*params_set) (GstRTSPClient *client, GstRTSPContext *ctx); + GstRTSPResult (*params_get) (GstRTSPClient *client, GstRTSPContext *ctx); + gchar * (*make_path_from_uri) (GstRTSPClient *client, const GstRTSPUrl *uri); + gboolean (*handle_options_request) (GstRTSPClient * client, GstRTSPContext * ctx); + gboolean (*handle_set_param_request) (GstRTSPClient * client, GstRTSPContext * ctx); + gboolean (*handle_get_param_request) (GstRTSPClient * client, GstRTSPContext * ctx); + + /* signals */ + void (*closed) (GstRTSPClient *client); + void (*new_session) (GstRTSPClient *client, GstRTSPSession *session); + void (*options_request) (GstRTSPClient *client, GstRTSPContext *ctx); + void (*describe_request) (GstRTSPClient *client, GstRTSPContext *ctx); + void (*setup_request) (GstRTSPClient *client, GstRTSPContext *ctx); + void (*play_request) (GstRTSPClient *client, GstRTSPContext *ctx); + void (*pause_request) (GstRTSPClient *client, GstRTSPContext *ctx); + void (*teardown_request) (GstRTSPClient *client, GstRTSPContext *ctx); + void (*set_parameter_request) (GstRTSPClient *client, GstRTSPContext *ctx); + void (*get_parameter_request) (GstRTSPClient *client, GstRTSPContext *ctx); + void (*handle_response) (GstRTSPClient *client, GstRTSPContext *ctx); + + void (*tunnel_http_response) (GstRTSPClient * client, GstRTSPMessage * request, + GstRTSPMessage * response); + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE-1]; +}; + +GType gst_rtsp_client_get_type (void); + +GstRTSPClient * gst_rtsp_client_new (void); + +void gst_rtsp_client_set_session_pool (GstRTSPClient *client, + GstRTSPSessionPool *pool); +GstRTSPSessionPool * gst_rtsp_client_get_session_pool (GstRTSPClient *client); + +void gst_rtsp_client_set_mount_points (GstRTSPClient *client, + GstRTSPMountPoints *mounts); +GstRTSPMountPoints * gst_rtsp_client_get_mount_points (GstRTSPClient *client); + +void gst_rtsp_client_set_auth (GstRTSPClient *client, GstRTSPAuth *auth); +GstRTSPAuth * gst_rtsp_client_get_auth (GstRTSPClient *client); + +void gst_rtsp_client_set_thread_pool (GstRTSPClient *client, GstRTSPThreadPool *pool); +GstRTSPThreadPool * gst_rtsp_client_get_thread_pool (GstRTSPClient *client); + +gboolean gst_rtsp_client_set_connection (GstRTSPClient *client, GstRTSPConnection *conn); +GstRTSPConnection * gst_rtsp_client_get_connection (GstRTSPClient *client); + +guint gst_rtsp_client_attach (GstRTSPClient *client, + GMainContext *context); +void gst_rtsp_client_close (GstRTSPClient * client); + +void gst_rtsp_client_set_send_func (GstRTSPClient *client, + GstRTSPClientSendFunc func, + gpointer user_data, + GDestroyNotify notify); + +GstRTSPResult gst_rtsp_client_handle_message (GstRTSPClient *client, + GstRTSPMessage *message); +GstRTSPResult gst_rtsp_client_send_message (GstRTSPClient * client, + GstRTSPSession *session, + GstRTSPMessage *message); +/** + * GstRTSPClientSessionFilterFunc: + * @client: a #GstRTSPClient object + * @sess: a #GstRTSPSession in @client + * @user_data: user data that has been given to gst_rtsp_client_session_filter() + * + * This function will be called by the gst_rtsp_client_session_filter(). An + * implementation should return a value of #GstRTSPFilterResult. + * + * When this function returns #GST_RTSP_FILTER_REMOVE, @sess will be removed + * from @client. + * + * A return value of #GST_RTSP_FILTER_KEEP will leave @sess untouched in + * @client. + * + * A value of #GST_RTSP_FILTER_REF will add @sess to the result #GList of + * gst_rtsp_client_session_filter(). + * + * Returns: a #GstRTSPFilterResult. + */ +typedef GstRTSPFilterResult (*GstRTSPClientSessionFilterFunc) (GstRTSPClient *client, + GstRTSPSession *sess, + gpointer user_data); + +GList * gst_rtsp_client_session_filter (GstRTSPClient *client, + GstRTSPClientSessionFilterFunc func, + gpointer user_data); + + + +G_END_DECLS + +#endif /* __GST_RTSP_CLIENT_H__ */ diff --git a/gst/rtsp-server/rtsp-context.c b/gst/rtsp-server/rtsp-context.c new file mode 100644 index 0000000..919ca2d --- /dev/null +++ b/gst/rtsp-server/rtsp-context.c @@ -0,0 +1,92 @@ +/* GStreamer + * Copyright (C) 2013 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-context + * @short_description: A client request context + * @see_also: #GstRTSPServer, #GstRTSPClient + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include "rtsp-context.h" + +G_DEFINE_POINTER_TYPE (GstRTSPContext, gst_rtsp_context); + +static GPrivate current_context; + +/** + * gst_rtsp_context_get_current: + * + * Get the current #GstRTSPContext. This object is retrieved from the + * current thread that is handling the request for a client. + * + * Returns: a #GstRTSPContext + */ +GstRTSPContext * +gst_rtsp_context_get_current (void) +{ + GSList *l; + + l = g_private_get (¤t_context); + if (l == NULL) + return NULL; + + return (GstRTSPContext *) (l->data); + +} + +/** + * gst_rtsp_context_push_current: + * @ctx: a ##GstRTSPContext + * + * Pushes @ctx onto the context stack. The current + * context can then be received using gst_rtsp_context_get_current(). + **/ +void +gst_rtsp_context_push_current (GstRTSPContext * ctx) +{ + GSList *l; + + g_return_if_fail (ctx != NULL); + + l = g_private_get (¤t_context); + l = g_slist_prepend (l, ctx); + g_private_set (¤t_context, l); +} + +/** + * gst_rtsp_context_pop_current: + * @ctx: a #GstRTSPContext + * + * Pops @ctx off the context stack (verifying that @ctx + * is on the top of the stack). + **/ +void +gst_rtsp_context_pop_current (GstRTSPContext * ctx) +{ + GSList *l; + + l = g_private_get (¤t_context); + + g_return_if_fail (l != NULL); + g_return_if_fail (l->data == ctx); + + l = g_slist_delete_link (l, l); + g_private_set (¤t_context, l); +} diff --git a/gst/rtsp-server/rtsp-context.h b/gst/rtsp-server/rtsp-context.h new file mode 100644 index 0000000..c2be87e --- /dev/null +++ b/gst/rtsp-server/rtsp-context.h @@ -0,0 +1,88 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include +#include + +#ifndef __GST_RTSP_CONTEXT_H__ +#define __GST_RTSP_CONTEXT_H__ + +G_BEGIN_DECLS + +#define GST_TYPE_RTSP_CONTEXT (gst_rtsp_context_get_type ()) + +typedef struct _GstRTSPContext GstRTSPContext; + +#include "rtsp-server.h" +#include "rtsp-media.h" +#include "rtsp-media-factory.h" +#include "rtsp-session-media.h" +#include "rtsp-auth.h" +#include "rtsp-thread-pool.h" +#include "rtsp-token.h" + +/** + * GstRTSPContext: + * @server: the server + * @conn: the connection + * @client: the client + * @request: the complete request + * @uri: the complete url parsed from @request + * @method: the parsed method of @uri + * @auth: the current auth object or %NULL + * @token: authorisation token + * @session: the session, can be %NULL + * @sessmedia: the session media for the url can be %NULL + * @factory: the media factory for the url, can be %NULL + * @media: the media for the url can be %NULL + * @stream: the stream for the url can be %NULL + * @response: the response + * + * Information passed around containing the context of a request. + */ +struct _GstRTSPContext { + GstRTSPServer *server; + GstRTSPConnection *conn; + GstRTSPClient *client; + GstRTSPMessage *request; + GstRTSPUrl *uri; + GstRTSPMethod method; + GstRTSPAuth *auth; + GstRTSPToken *token; + GstRTSPSession *session; + GstRTSPSessionMedia *sessmedia; + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPStream *stream; + GstRTSPMessage *response; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_rtsp_context_get_type (void); + +GstRTSPContext * gst_rtsp_context_get_current (void); +void gst_rtsp_context_push_current (GstRTSPContext * ctx); +void gst_rtsp_context_pop_current (GstRTSPContext * ctx); + + +G_END_DECLS + +#endif /* __GST_RTSP_CONTEXT_H__ */ diff --git a/gst/rtsp-server/rtsp-media-factory-uri.c b/gst/rtsp-server/rtsp-media-factory-uri.c new file mode 100644 index 0000000..01f3f99 --- /dev/null +++ b/gst/rtsp-server/rtsp-media-factory-uri.c @@ -0,0 +1,645 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-media-factory-uri + * @short_description: A factory for URI sources + * @see_also: #GstRTSPMediaFactory, #GstRTSPMedia + * + * This specialized #GstRTSPMediaFactory constructs media pipelines from a URI, + * given with gst_rtsp_media_factory_uri_set_uri(). + * + * It will automatically demux and payload the different streams found in the + * media at URL. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include + +#include "rtsp-media-factory-uri.h" + +#define GST_RTSP_MEDIA_FACTORY_URI_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_URI, GstRTSPMediaFactoryURIPrivate)) + +struct _GstRTSPMediaFactoryURIPrivate +{ + GMutex lock; + gchar *uri; /* protected by lock */ + gboolean use_gstpay; + + GstCaps *raw_vcaps; + GstCaps *raw_acaps; + GList *demuxers; + GList *payloaders; + GList *decoders; +}; + +#define DEFAULT_URI NULL +#define DEFAULT_USE_GSTPAY FALSE + +enum +{ + PROP_0, + PROP_URI, + PROP_USE_GSTPAY, + PROP_LAST +}; + + +#define RAW_VIDEO_CAPS \ + "video/x-raw" + +#define RAW_AUDIO_CAPS \ + "audio/x-raw" + +static GstStaticCaps raw_video_caps = GST_STATIC_CAPS (RAW_VIDEO_CAPS); +static GstStaticCaps raw_audio_caps = GST_STATIC_CAPS (RAW_AUDIO_CAPS); + +typedef struct +{ + GstRTSPMediaFactoryURI *factory; + guint pt; +} FactoryData; + +static void +free_data (FactoryData * data) +{ + g_object_unref (data->factory); + g_free (data); +} + +static const gchar *factory_key = "GstRTSPMediaFactoryURI"; + +GST_DEBUG_CATEGORY_STATIC (rtsp_media_factory_uri_debug); +#define GST_CAT_DEFAULT rtsp_media_factory_uri_debug + +static void gst_rtsp_media_factory_uri_get_property (GObject * object, + guint propid, GValue * value, GParamSpec * pspec); +static void gst_rtsp_media_factory_uri_set_property (GObject * object, + guint propid, const GValue * value, GParamSpec * pspec); +static void gst_rtsp_media_factory_uri_finalize (GObject * obj); + +static GstElement *rtsp_media_factory_uri_create_element (GstRTSPMediaFactory * + factory, const GstRTSPUrl * url); + +G_DEFINE_TYPE (GstRTSPMediaFactoryURI, gst_rtsp_media_factory_uri, + GST_TYPE_RTSP_MEDIA_FACTORY); + +static void +gst_rtsp_media_factory_uri_class_init (GstRTSPMediaFactoryURIClass * klass) +{ + GObjectClass *gobject_class; + GstRTSPMediaFactoryClass *mediafactory_class; + + g_type_class_add_private (klass, sizeof (GstRTSPMediaFactoryURIPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + mediafactory_class = GST_RTSP_MEDIA_FACTORY_CLASS (klass); + + gobject_class->get_property = gst_rtsp_media_factory_uri_get_property; + gobject_class->set_property = gst_rtsp_media_factory_uri_set_property; + gobject_class->finalize = gst_rtsp_media_factory_uri_finalize; + + /** + * GstRTSPMediaFactoryURI::uri: + * + * The uri of the resource that will be served by this factory. + */ + g_object_class_install_property (gobject_class, PROP_URI, + g_param_spec_string ("uri", "URI", + "The URI of the resource to stream", DEFAULT_URI, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstRTSPMediaFactoryURI::use-gstpay: + * + * Allow the usage of gstpay in order to avoid decoding of compressed formats + * without a payloader. + */ + g_object_class_install_property (gobject_class, PROP_USE_GSTPAY, + g_param_spec_boolean ("use-gstpay", "Use gstpay", + "Use the gstpay payloader to avoid decoding", DEFAULT_USE_GSTPAY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + mediafactory_class->create_element = rtsp_media_factory_uri_create_element; + + GST_DEBUG_CATEGORY_INIT (rtsp_media_factory_uri_debug, "rtspmediafactoryuri", + 0, "GstRTSPMediaFactoryUri"); +} + +typedef struct +{ + GList *demux; + GList *payload; + GList *decode; +} FilterData; + +static gboolean +payloader_filter (GstPluginFeature * feature, FilterData * data) +{ + const gchar *klass; + GstElementFactory *fact; + GList **list = NULL; + + /* we only care about element factories */ + if (G_UNLIKELY (!GST_IS_ELEMENT_FACTORY (feature))) + return FALSE; + + if (gst_plugin_feature_get_rank (feature) < GST_RANK_MARGINAL) + return FALSE; + + fact = GST_ELEMENT_FACTORY_CAST (feature); + + klass = gst_element_factory_get_metadata (fact, GST_ELEMENT_METADATA_KLASS); + + if (strstr (klass, "Decoder")) + list = &data->decode; + else if (strstr (klass, "Demux")) + list = &data->demux; + else if (strstr (klass, "Parser") && strstr (klass, "Codec")) + list = &data->demux; + else if (strstr (klass, "Payloader") && strstr (klass, "RTP")) + list = &data->payload; + + if (list) { + GST_DEBUG ("adding %s", GST_OBJECT_NAME (fact)); + *list = g_list_prepend (*list, gst_object_ref (fact)); + } + + return FALSE; +} + +static void +gst_rtsp_media_factory_uri_init (GstRTSPMediaFactoryURI * factory) +{ + GstRTSPMediaFactoryURIPrivate *priv = + GST_RTSP_MEDIA_FACTORY_URI_GET_PRIVATE (factory); + FilterData data = { NULL, NULL, NULL }; + + GST_DEBUG_OBJECT (factory, "new"); + + factory->priv = priv; + + priv->uri = g_strdup (DEFAULT_URI); + priv->use_gstpay = DEFAULT_USE_GSTPAY; + g_mutex_init (&priv->lock); + + /* get the feature list using the filter */ + gst_registry_feature_filter (gst_registry_get (), (GstPluginFeatureFilter) + payloader_filter, FALSE, &data); + /* sort */ + priv->demuxers = + g_list_sort (data.demux, gst_plugin_feature_rank_compare_func); + priv->payloaders = + g_list_sort (data.payload, gst_plugin_feature_rank_compare_func); + priv->decoders = + g_list_sort (data.decode, gst_plugin_feature_rank_compare_func); + + priv->raw_vcaps = gst_static_caps_get (&raw_video_caps); + priv->raw_acaps = gst_static_caps_get (&raw_audio_caps); +} + +static void +gst_rtsp_media_factory_uri_finalize (GObject * obj) +{ + GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (obj); + GstRTSPMediaFactoryURIPrivate *priv = factory->priv; + + GST_DEBUG_OBJECT (factory, "finalize"); + + g_free (priv->uri); + gst_plugin_feature_list_free (priv->demuxers); + gst_plugin_feature_list_free (priv->payloaders); + gst_plugin_feature_list_free (priv->decoders); + gst_caps_unref (priv->raw_vcaps); + gst_caps_unref (priv->raw_acaps); + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (gst_rtsp_media_factory_uri_parent_class)->finalize (obj); +} + +static void +gst_rtsp_media_factory_uri_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (object); + GstRTSPMediaFactoryURIPrivate *priv = factory->priv; + + switch (propid) { + case PROP_URI: + g_value_take_string (value, gst_rtsp_media_factory_uri_get_uri (factory)); + break; + case PROP_USE_GSTPAY: + g_value_set_boolean (value, priv->use_gstpay); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_media_factory_uri_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (object); + GstRTSPMediaFactoryURIPrivate *priv = factory->priv; + + switch (propid) { + case PROP_URI: + gst_rtsp_media_factory_uri_set_uri (factory, g_value_get_string (value)); + break; + case PROP_USE_GSTPAY: + priv->use_gstpay = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +/** + * gst_rtsp_media_factory_uri_new: + * + * Create a new #GstRTSPMediaFactoryURI instance. + * + * Returns: (transfer full): a new #GstRTSPMediaFactoryURI object. + */ +GstRTSPMediaFactoryURI * +gst_rtsp_media_factory_uri_new (void) +{ + GstRTSPMediaFactoryURI *result; + + result = g_object_new (GST_TYPE_RTSP_MEDIA_FACTORY_URI, NULL); + + return result; +} + +/** + * gst_rtsp_media_factory_uri_set_uri: + * @factory: a #GstRTSPMediaFactory + * @uri: the uri the stream + * + * Set the URI of the resource that will be streamed by this factory. + */ +void +gst_rtsp_media_factory_uri_set_uri (GstRTSPMediaFactoryURI * factory, + const gchar * uri) +{ + GstRTSPMediaFactoryURIPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY_URI (factory)); + g_return_if_fail (uri != NULL); + + priv = factory->priv; + + g_mutex_lock (&priv->lock); + g_free (priv->uri); + priv->uri = g_strdup (uri); + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_media_factory_uri_get_uri: + * @factory: a #GstRTSPMediaFactory + * + * Get the URI that will provide media for this factory. + * + * Returns: (transfer full): the configured URI. g_free() after usage. + */ +gchar * +gst_rtsp_media_factory_uri_get_uri (GstRTSPMediaFactoryURI * factory) +{ + GstRTSPMediaFactoryURIPrivate *priv; + gchar *result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY_URI (factory), NULL); + + priv = factory->priv; + + g_mutex_lock (&priv->lock); + result = g_strdup (priv->uri); + g_mutex_unlock (&priv->lock); + + return result; +} + +static GstElementFactory * +find_payloader (GstRTSPMediaFactoryURI * urifact, GstCaps * caps) +{ + GstRTSPMediaFactoryURIPrivate *priv = urifact->priv; + GList *list; + GstElementFactory *factory = NULL; + gboolean autoplug_more = FALSE; + + /* first find a demuxer that can link */ + list = gst_element_factory_list_filter (priv->demuxers, caps, + GST_PAD_SINK, FALSE); + + if (list) { + GstStructure *structure = gst_caps_get_structure (caps, 0); + gboolean parsed = FALSE; + gint mpegversion = 0; + + if (!gst_structure_get_boolean (structure, "parsed", &parsed) && + gst_structure_has_name (structure, "audio/mpeg") && + gst_structure_get_int (structure, "mpegversion", &mpegversion) && + (mpegversion == 2 || mpegversion == 4)) { + /* for AAC it's framed=true instead of parsed=true */ + gst_structure_get_boolean (structure, "framed", &parsed); + } + + /* Avoid plugging parsers in a loop. This is not 100% correct, as some + * parsers don't set parsed=true in caps. We should do something like + * decodebin does and track decode chains and elements plugged in those + * chains... + */ + if (parsed) { + GList *walk; + const gchar *klass; + + for (walk = list; walk; walk = walk->next) { + factory = GST_ELEMENT_FACTORY (walk->data); + klass = gst_element_factory_get_metadata (factory, + GST_ELEMENT_METADATA_KLASS); + if (strstr (klass, "Parser")) + /* caps have parsed=true, so skip this parser to avoid loops */ + continue; + + autoplug_more = TRUE; + break; + } + } else { + /* caps don't have parsed=true set and we have a demuxer/parser */ + autoplug_more = TRUE; + } + + gst_plugin_feature_list_free (list); + } + + if (autoplug_more) + /* we have a demuxer, try that one first */ + return NULL; + + /* no demuxer try a depayloader */ + list = gst_element_factory_list_filter (priv->payloaders, caps, + GST_PAD_SINK, FALSE); + + if (list == NULL) { + if (priv->use_gstpay) { + /* no depayloader or parser/demuxer, use gstpay when allowed */ + factory = gst_element_factory_find ("rtpgstpay"); + } else { + /* no depayloader, try a decoder, we'll get to a payloader for a decoded + * video or audio format, worst case. */ + list = gst_element_factory_list_filter (priv->decoders, caps, + GST_PAD_SINK, FALSE); + + if (list != NULL) { + /* we have a decoder, try that one first */ + gst_plugin_feature_list_free (list); + return NULL; + } + } + } + + if (list != NULL) { + factory = GST_ELEMENT_FACTORY_CAST (list->data); + g_object_ref (factory); + gst_plugin_feature_list_free (list); + } + return factory; +} + +static gboolean +autoplug_continue_cb (GstElement * uribin, GstPad * pad, GstCaps * caps, + GstElement * element) +{ + FactoryData *data; + GstElementFactory *factory; + + GST_DEBUG ("found pad %s:%s of caps %" GST_PTR_FORMAT, + GST_DEBUG_PAD_NAME (pad), caps); + + data = g_object_get_data (G_OBJECT (element), factory_key); + + if (!(factory = find_payloader (data->factory, caps))) + goto no_factory; + + /* we found a payloader, stop autoplugging so we can plug the + * payloader. */ + GST_DEBUG ("found factory %s", + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); + gst_object_unref (factory); + + return FALSE; + + /* ERRORS */ +no_factory: + { + /* no payloader, continue autoplugging */ + GST_DEBUG ("no payloader found"); + return TRUE; + } +} + +static void +pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element) +{ + GstRTSPMediaFactoryURI *urifact; + GstRTSPMediaFactoryURIPrivate *priv; + FactoryData *data; + GstElementFactory *factory; + GstElement *payloader; + GstCaps *caps; + GstPad *sinkpad, *srcpad, *ghostpad; + GstElement *convert; + gchar *padname; + + GST_DEBUG ("added pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + /* link the element now and expose the pad */ + data = g_object_get_data (G_OBJECT (element), factory_key); + urifact = data->factory; + priv = urifact->priv; + + /* ref to make refcounting easier later */ + gst_object_ref (pad); + padname = gst_pad_get_name (pad); + + /* get pad caps first, then call get_caps, then fail */ + if ((caps = gst_pad_get_current_caps (pad)) == NULL) + if ((caps = gst_pad_query_caps (pad, NULL)) == NULL) + goto no_caps; + + /* check for raw caps */ + if (gst_caps_can_intersect (caps, priv->raw_vcaps)) { + /* we have raw video caps, insert converter */ + convert = gst_element_factory_make ("videoconvert", NULL); + } else if (gst_caps_can_intersect (caps, priv->raw_acaps)) { + /* we have raw audio caps, insert converter */ + convert = gst_element_factory_make ("audioconvert", NULL); + } else { + convert = NULL; + } + + if (convert) { + gst_bin_add (GST_BIN_CAST (element), convert); + gst_element_set_state (convert, GST_STATE_PLAYING); + + sinkpad = gst_element_get_static_pad (convert, "sink"); + gst_pad_link (pad, sinkpad); + gst_object_unref (sinkpad); + + /* unref old pad, we reffed before */ + gst_object_unref (pad); + + /* continue with new pad and caps */ + pad = gst_element_get_static_pad (convert, "src"); + if ((caps = gst_pad_get_current_caps (pad)) == NULL) + if ((caps = gst_pad_query_caps (pad, NULL)) == NULL) + goto no_caps; + } + + if (!(factory = find_payloader (urifact, caps))) + goto no_factory; + + gst_caps_unref (caps); + + /* we have a payloader now */ + GST_DEBUG ("found payloader factory %s", + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); + + payloader = gst_element_factory_create (factory, NULL); + if (payloader == NULL) + goto no_payloader; + + g_object_set (payloader, "pt", data->pt, NULL); + data->pt++; + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (payloader), + "buffer-list")) + g_object_set (payloader, "buffer-list", TRUE, NULL); + + /* add the payloader to the pipeline */ + gst_bin_add (GST_BIN_CAST (element), payloader); + gst_element_set_state (payloader, GST_STATE_PLAYING); + + /* link the pad to the sinkpad of the payloader */ + sinkpad = gst_element_get_static_pad (payloader, "sink"); + gst_pad_link (pad, sinkpad); + gst_object_unref (sinkpad); + gst_object_unref (pad); + + /* now expose the srcpad of the payloader as a ghostpad with the same name + * as the uridecodebin pad name. */ + srcpad = gst_element_get_static_pad (payloader, "src"); + ghostpad = gst_ghost_pad_new (padname, srcpad); + gst_object_unref (srcpad); + g_free (padname); + + gst_pad_set_active (ghostpad, TRUE); + gst_element_add_pad (element, ghostpad); + + return; + + /* ERRORS */ +no_caps: + { + GST_WARNING ("could not get caps from pad"); + g_free (padname); + gst_object_unref (pad); + return; + } +no_factory: + { + GST_DEBUG ("no payloader found"); + g_free (padname); + gst_caps_unref (caps); + gst_object_unref (pad); + return; + } +no_payloader: + { + GST_ERROR ("could not create payloader from factory"); + g_free (padname); + gst_caps_unref (caps); + gst_object_unref (pad); + return; + } +} + +static void +no_more_pads_cb (GstElement * uribin, GstElement * element) +{ + GST_DEBUG ("no-more-pads"); + gst_element_no_more_pads (element); +} + +static GstElement * +rtsp_media_factory_uri_create_element (GstRTSPMediaFactory * factory, + const GstRTSPUrl * url) +{ + GstRTSPMediaFactoryURIPrivate *priv; + GstElement *topbin, *element, *uribin; + GstRTSPMediaFactoryURI *urifact; + FactoryData *data; + + urifact = GST_RTSP_MEDIA_FACTORY_URI_CAST (factory); + priv = urifact->priv; + + GST_LOG ("creating element"); + + topbin = gst_bin_new ("GstRTSPMediaFactoryURI"); + g_assert (topbin != NULL); + + /* our bin will dynamically expose payloaded pads */ + element = gst_bin_new ("dynpay0"); + g_assert (element != NULL); + + uribin = gst_element_factory_make ("uridecodebin", "uribin"); + if (uribin == NULL) + goto no_uridecodebin; + + g_object_set (uribin, "uri", priv->uri, NULL); + + /* keep factory data around */ + data = g_new0 (FactoryData, 1); + data->factory = g_object_ref (factory); + data->pt = 96; + + g_object_set_data_full (G_OBJECT (element), factory_key, + data, (GDestroyNotify) free_data); + + /* connect to the signals */ + g_signal_connect (uribin, "autoplug-continue", + (GCallback) autoplug_continue_cb, element); + g_signal_connect (uribin, "pad-added", (GCallback) pad_added_cb, element); + g_signal_connect (uribin, "no-more-pads", (GCallback) no_more_pads_cb, + element); + + gst_bin_add (GST_BIN_CAST (element), uribin); + gst_bin_add (GST_BIN_CAST (topbin), element); + + return topbin; + +no_uridecodebin: + { + g_critical ("can't create uridecodebin element"); + gst_object_unref (element); + return NULL; + } +} diff --git a/gst/rtsp-server/rtsp-media-factory-uri.h b/gst/rtsp-server/rtsp-media-factory-uri.h new file mode 100644 index 0000000..6dc3a40 --- /dev/null +++ b/gst/rtsp-server/rtsp-media-factory-uri.h @@ -0,0 +1,80 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include "rtsp-media-factory.h" + +#ifndef __GST_RTSP_MEDIA_FACTORY_URI_H__ +#define __GST_RTSP_MEDIA_FACTORY_URI_H__ + +G_BEGIN_DECLS + +/* types for the media factory */ +#define GST_TYPE_RTSP_MEDIA_FACTORY_URI (gst_rtsp_media_factory_uri_get_type ()) +#define GST_IS_RTSP_MEDIA_FACTORY_URI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_URI)) +#define GST_IS_RTSP_MEDIA_FACTORY_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_MEDIA_FACTORY_URI)) +#define GST_RTSP_MEDIA_FACTORY_URI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_URI, GstRTSPMediaFactoryURIClass)) +#define GST_RTSP_MEDIA_FACTORY_URI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_URI, GstRTSPMediaFactoryURI)) +#define GST_RTSP_MEDIA_FACTORY_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_MEDIA_FACTORY_URI, GstRTSPMediaFactoryURIClass)) +#define GST_RTSP_MEDIA_FACTORY_URI_CAST(obj) ((GstRTSPMediaFactoryURI*)(obj)) +#define GST_RTSP_MEDIA_FACTORY_URI_CLASS_CAST(klass) ((GstRTSPMediaFactoryURIClass*)(klass)) + +typedef struct _GstRTSPMediaFactoryURI GstRTSPMediaFactoryURI; +typedef struct _GstRTSPMediaFactoryURIClass GstRTSPMediaFactoryURIClass; +typedef struct _GstRTSPMediaFactoryURIPrivate GstRTSPMediaFactoryURIPrivate; + +/** + * GstRTSPMediaFactoryURI: + * + * A media factory that creates a pipeline to play and uri. + */ +struct _GstRTSPMediaFactoryURI { + GstRTSPMediaFactory parent; + + /*< private >*/ + GstRTSPMediaFactoryURIPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPMediaFactoryURIClass: + * + * The #GstRTSPMediaFactoryURI class structure. + */ +struct _GstRTSPMediaFactoryURIClass { + GstRTSPMediaFactoryClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_rtsp_media_factory_uri_get_type (void); + +/* creating the factory */ +GstRTSPMediaFactoryURI * gst_rtsp_media_factory_uri_new (void); + +/* configuring the factory */ +void gst_rtsp_media_factory_uri_set_uri (GstRTSPMediaFactoryURI *factory, + const gchar *uri); +gchar * gst_rtsp_media_factory_uri_get_uri (GstRTSPMediaFactoryURI *factory); + +G_END_DECLS + +#endif /* __GST_RTSP_MEDIA_FACTORY_URI_H__ */ diff --git a/gst/rtsp-server/rtsp-media-factory-wfd.c b/gst/rtsp-server/rtsp-media-factory-wfd.c new file mode 100644 index 0000000..e083fa6 --- /dev/null +++ b/gst/rtsp-server/rtsp-media-factory-wfd.c @@ -0,0 +1,1111 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-media-factory + * @short_description: A factory for media pipelines + * @see_also: #GstRTSPMountPoints, #GstRTSPMedia + * + * The #GstRTSPMediaFactoryWFD is responsible for creating or recycling + * #GstRTSPMedia objects based on the passed URL. + * + * The default implementation of the object can create #GstRTSPMedia objects + * containing a pipeline created from a launch description set with + * gst_rtsp_media_factory_wfd_set_launch(). + * + * Media from a factory can be shared by setting the shared flag with + * gst_rtsp_media_factory_wfd_set_shared(). When a factory is shared, + * gst_rtsp_media_factory_wfd_construct() will return the same #GstRTSPMedia when + * the url matches. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include +#include "rtsp-media-factory-wfd.h" +#include "gstwfdmessage.h" + +#define GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_WFD, GstRTSPMediaFactoryWFDPrivate)) + +#define GST_RTSP_MEDIA_FACTORY_WFD_GET_LOCK(f) (&(GST_RTSP_MEDIA_FACTORY_WFD_CAST(f)->priv->lock)) +#define GST_RTSP_MEDIA_FACTORY_WFD_LOCK(f) (g_mutex_lock(GST_RTSP_MEDIA_FACTORY_WFD_GET_LOCK(f))) +#define GST_RTSP_MEDIA_FACTORY_WFD_UNLOCK(f) (g_mutex_unlock(GST_RTSP_MEDIA_FACTORY_WFD_GET_LOCK(f))) + +struct _GstRTSPMediaFactoryWFDPrivate +{ + GMutex lock; + GstRTSPPermissions *permissions; + gchar *launch; + gboolean shared; + GstRTSPLowerTrans protocols; + guint buffer_size; + guint mtu_size; + + guint8 videosrc_type; + guint8 video_codec; + gchar *video_encoder; + guint video_bitrate; + guint video_width; + guint video_height; + guint video_framerate; + guint video_enc_skip_inbuf_value; + GstElement *video_queue; + + gchar *audio_device; + gchar *audio_encoder_aac; + gchar *audio_encoder_ac3; + guint8 audio_codec; + guint64 audio_latency_time; + guint64 audio_buffer_time; + gboolean audio_do_timestamp; + guint8 audio_channels; + guint8 audio_freq; + guint8 audio_bitrate; + GstElement *audio_queue; + + guint64 video_resolution_supported; + + gboolean dump_ts; +}; + +#define DEFAULT_LAUNCH NULL +#define DEFAULT_SHARED FALSE +#define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \ + GST_RTSP_LOWER_TRANS_TCP +#define DEFAULT_BUFFER_SIZE 0x80000 + +enum +{ + PROP_0, + PROP_LAUNCH, + PROP_SHARED, + PROP_SUSPEND_MODE, + PROP_EOS_SHUTDOWN, + PROP_PROTOCOLS, + PROP_BUFFER_SIZE, + PROP_LAST +}; + +enum +{ + SIGNAL_MEDIA_CONSTRUCTED, + SIGNAL_MEDIA_CONFIGURE, + SIGNAL_LAST +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_media_wfd_debug); +#define GST_CAT_DEFAULT rtsp_media_wfd_debug + +static void gst_rtsp_media_factory_wfd_get_property (GObject * object, + guint propid, GValue * value, GParamSpec * pspec); +static void gst_rtsp_media_factory_wfd_set_property (GObject * object, + guint propid, const GValue * value, GParamSpec * pspec); + +static void gst_rtsp_media_factory_wfd_finalize (GObject * obj); + + +static GstElement *rtsp_media_factory_wfd_create_element (GstRTSPMediaFactory * + factory, const GstRTSPUrl * url); +static GstRTSPMedia *rtsp_media_factory_wfd_construct (GstRTSPMediaFactory * + factory, const GstRTSPUrl * url); + +G_DEFINE_TYPE (GstRTSPMediaFactoryWFD, gst_rtsp_media_factory_wfd, + GST_TYPE_RTSP_MEDIA_FACTORY); + +static void +gst_rtsp_media_factory_wfd_class_init (GstRTSPMediaFactoryWFDClass * klass) +{ + GObjectClass *gobject_class; + GstRTSPMediaFactoryClass *factory_class; + + g_type_class_add_private (klass, sizeof (GstRTSPMediaFactoryWFDPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + factory_class = GST_RTSP_MEDIA_FACTORY_CLASS (klass); + + gobject_class->get_property = gst_rtsp_media_factory_wfd_get_property; + gobject_class->set_property = gst_rtsp_media_factory_wfd_set_property; + gobject_class->finalize = gst_rtsp_media_factory_wfd_finalize; + + factory_class->construct = rtsp_media_factory_wfd_construct; + factory_class->create_element = rtsp_media_factory_wfd_create_element; + + GST_DEBUG_CATEGORY_INIT (rtsp_media_wfd_debug, "rtspmediafactorywfd", 0, + "GstRTSPMediaFactoryWFD"); +} + +void gst_rtsp_media_factory_wfd_set (GstRTSPMediaFactoryWFD * factory, + guint8 videosrc_type, gchar *audio_device, guint64 audio_latency_time, + guint64 audio_buffer_time, gboolean audio_do_timestamp, guint mtu_size) +{ + GstRTSPMediaFactoryWFDPrivate *priv = + GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory); + factory->priv = priv; + + priv->videosrc_type = videosrc_type; + priv->audio_device = audio_device; + priv->audio_latency_time = audio_latency_time; + priv->audio_buffer_time = audio_buffer_time; + priv->audio_do_timestamp = audio_do_timestamp; + priv->mtu_size = mtu_size; +} + +void gst_rtsp_media_factory_wfd_set_encoders (GstRTSPMediaFactoryWFD * factory, + gchar *video_encoder, gchar *audio_encoder_aac, gchar *audio_encoder_ac3) +{ + GstRTSPMediaFactoryWFDPrivate *priv = + GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory); + factory->priv = priv; + + priv->video_encoder = video_encoder; + priv->audio_encoder_aac = audio_encoder_aac; + priv->audio_encoder_ac3 = audio_encoder_ac3; +} + +void gst_rtsp_media_factory_wfd_set_dump_ts (GstRTSPMediaFactoryWFD * factory, + gboolean dump_ts) +{ + GstRTSPMediaFactoryWFDPrivate *priv = + GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory); + factory->priv = priv; + + priv->dump_ts = dump_ts; +} +void gst_rtsp_media_factory_wfd_set_negotiated_resolution (GstRTSPMediaFactory *factory, + guint32 width, guint32 height) +{ + GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory); + GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv; + + priv->video_width = width; + priv->video_height = height; +} +void gst_rtsp_media_factory_wfd_set_audio_codec (GstRTSPMediaFactory *factory, + guint audio_codec) +{ + GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory); + GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv; + + priv->audio_codec = audio_codec; +} + +static void +gst_rtsp_media_factory_wfd_init (GstRTSPMediaFactoryWFD * factory) +{ + GstRTSPMediaFactoryWFDPrivate *priv = + GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory); + factory->priv = priv; + + priv->launch = g_strdup (DEFAULT_LAUNCH); + priv->shared = DEFAULT_SHARED; + priv->protocols = DEFAULT_PROTOCOLS; + priv->buffer_size = DEFAULT_BUFFER_SIZE; + + //priv->videosrc_type = GST_WFD_VSRC_XIMAGESRC; + //priv->videosrc_type = GST_WFD_VSRC_XVIMAGESRC; + //priv->videosrc_type = GST_WFD_VSRC_CAMERASRC; + priv->videosrc_type = GST_WFD_VSRC_VIDEOTESTSRC; + priv->video_codec = GST_WFD_VIDEO_H264; + priv->video_encoder = g_strdup ("omxh264enc"); + priv->video_bitrate = 200000; + priv->video_width = 640; + priv->video_height = 480; + priv->video_framerate = 30; + priv->video_enc_skip_inbuf_value = 5; + + priv->audio_device = g_strdup ("alsa_output.1.analog-stereo.monitor"); + priv->audio_codec = GST_WFD_AUDIO_AAC; + priv->audio_encoder_aac = g_strdup ("avenc_aac"); + priv->audio_encoder_ac3 = g_strdup ("avenc_ac3"); + priv->audio_latency_time = 10000; + priv->audio_buffer_time = 200000; + priv->audio_do_timestamp = FALSE; + priv->audio_channels = GST_WFD_CHANNEL_2; + priv->audio_freq = GST_WFD_FREQ_48000; + + g_mutex_init (&priv->lock); +} + +static void +gst_rtsp_media_factory_wfd_finalize (GObject * obj) +{ + GstRTSPMediaFactoryWFD *factory = GST_RTSP_MEDIA_FACTORY_WFD (obj); + GstRTSPMediaFactoryWFDPrivate *priv = factory->priv; + + if (priv->permissions) + gst_rtsp_permissions_unref (priv->permissions); + g_free (priv->launch); + g_mutex_clear (&priv->lock); + + if (priv->audio_device) + g_free (priv->audio_device); + if (priv->audio_encoder_aac) + g_free (priv->audio_encoder_aac); + if (priv->audio_encoder_ac3) + g_free (priv->audio_encoder_ac3); + + if (priv->video_encoder) + g_free (priv->video_encoder); + + G_OBJECT_CLASS (gst_rtsp_media_factory_wfd_parent_class)->finalize (obj); +} + +GstRTSPMediaFactoryWFD * +gst_rtsp_media_factory_wfd_new (void) +{ + GstRTSPMediaFactoryWFD *result; + + result = g_object_new (GST_TYPE_RTSP_MEDIA_FACTORY_WFD, NULL); + + return result; +} + +static void +gst_rtsp_media_factory_wfd_get_property (GObject * object, + guint propid, GValue * value, GParamSpec * pspec) +{ + //GstRTSPMediaFactoryWFD *factory = GST_RTSP_MEDIA_FACTORY_WFD (object); + + switch (propid) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_media_factory_wfd_set_property (GObject * object, + guint propid, const GValue * value, GParamSpec * pspec) +{ + //GstRTSPMediaFactoryWFD *factory = GST_RTSP_MEDIA_FACTORY_WFD (object); + + switch (propid) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static GstPadProbeReturn +rtsp_media_wfd_dump_data (GstPad * pad, GstPadProbeInfo *info, gpointer u_data) +{ + guint8 *data; + gsize size; + FILE *f; + GstMapInfo mapinfo; + + if (info->type == (GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH)) { + GstBuffer *buffer = gst_pad_probe_info_get_buffer (info); + + gst_buffer_map (buffer, &mapinfo, GST_MAP_READ); + data = mapinfo.data; + size = gst_buffer_get_size (buffer); + + f = fopen ("/root/probe.ts", "a"); + if (f != NULL) { + fwrite (data, size, 1, f); + fclose (f); + } + gst_buffer_unmap (buffer, &mapinfo); + } + + return GST_PAD_PROBE_OK; +} + +static gboolean +_rtsp_media_factory_wfd_create_audio_capture_bin (GstRTSPMediaFactoryWFD * + factory, GstBin * srcbin) +{ + GstElement *audiosrc = NULL; + GstElement *acaps = NULL; + GstElement *acaps2 = NULL; + GstElement *aenc = NULL; + GstElement *audio_convert = NULL; + GstElement *aqueue = NULL; + GstRTSPMediaFactoryWFDPrivate *priv = NULL; + + guint channels = 0; + gboolean is_enc_req = TRUE; + guint freq = 0; + gchar *acodec = NULL; + + priv = factory->priv; + + /* create audio src element */ + audiosrc = gst_element_factory_make ("pulsesrc", "audiosrc"); + if (!audiosrc) { + GST_ERROR_OBJECT (factory, "failed to create audiosrc element"); + goto create_error; + } + + GST_INFO_OBJECT (factory, "audio device : %s", priv->audio_device); + GST_INFO_OBJECT (factory, "audio latency time : %"G_GUINT64_FORMAT, + priv->audio_latency_time); + GST_INFO_OBJECT (factory, "audio_buffer_time : %"G_GUINT64_FORMAT, + priv->audio_buffer_time); + GST_INFO_OBJECT (factory, "audio_do_timestamp : %d", + priv->audio_do_timestamp); + + g_object_set (audiosrc, "device", priv->audio_device, NULL); + g_object_set (audiosrc, "buffer-time", (gint64) priv->audio_buffer_time, + NULL); + g_object_set (audiosrc, "latency-time", (gint64) priv->audio_latency_time, + NULL); + g_object_set (audiosrc, "do-timestamp", (gboolean) priv->audio_do_timestamp, + NULL); + g_object_set (audiosrc, "provide-clock", (gboolean) FALSE, NULL); + g_object_set (audiosrc, "is-live", (gboolean) TRUE, NULL); + + if (priv->audio_codec == GST_WFD_AUDIO_LPCM) { + /* To meet miracast certification */ + gint64 block_size = 1920; + g_object_set (audiosrc, "blocksize", (gint64) block_size, NULL); + + audio_convert = gst_element_factory_make ("capssetter", "audio_convert"); + if (NULL == audio_convert) { + GST_ERROR_OBJECT (factory, "failed to create audio convert element"); + goto create_error; + } + g_object_set (audio_convert, "caps", gst_caps_new_simple("audio/x-lpcm", + "width", G_TYPE_INT, 16, + "rate", G_TYPE_INT, 48000, + "channels", G_TYPE_INT, 2, + "dynamic_range", G_TYPE_INT, 0, + "emphasis", G_TYPE_BOOLEAN, FALSE, + "mute", G_TYPE_BOOLEAN, FALSE, NULL), NULL); + g_object_set (audio_convert, "join", (gboolean)FALSE, NULL); + g_object_set (audio_convert, "replace", (gboolean)TRUE, NULL); + + acaps2 = gst_element_factory_make ("capsfilter", "audiocaps2"); + if (NULL == acaps2) { + GST_ERROR_OBJECT (factory, "failed to create audio capsilfter element"); + goto create_error; + } + /* In case of LPCM, uses big endian */ + g_object_set (G_OBJECT (acaps2), "caps", + gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S16BE", + /* In case of LPCM, uses big endian */ + "rate", G_TYPE_INT, 48000, + "channels", G_TYPE_INT, 2, NULL), NULL); + } + + /* create audio caps element */ + acaps = gst_element_factory_make ("capsfilter", "audiocaps"); + if (NULL == acaps) { + GST_ERROR_OBJECT (factory, "failed to create audio capsilfter element"); + goto create_error; + } + + if (priv->audio_channels == GST_WFD_CHANNEL_2) + channels = 2; + else if (priv->audio_channels == GST_WFD_CHANNEL_4) + channels = 4; + else if (priv->audio_channels == GST_WFD_CHANNEL_6) + channels = 6; + else if (priv->audio_channels == GST_WFD_CHANNEL_8) + channels = 8; + else + channels = 2; + + if (priv->audio_freq == GST_WFD_FREQ_44100) + freq = 44100; + else if (priv->audio_freq == GST_WFD_FREQ_48000) + freq = 48000; + else + freq = 44100; + + if (priv->audio_codec == GST_WFD_AUDIO_LPCM) { + g_object_set (G_OBJECT (acaps), "caps", + gst_caps_new_simple ("audio/x-lpcm", "width", G_TYPE_INT, 16, + "rate", G_TYPE_INT, 48000, + "channels", G_TYPE_INT, 2, + "dynamic_range", G_TYPE_INT, 0, + "emphasis", G_TYPE_BOOLEAN, FALSE, + "mute", G_TYPE_BOOLEAN, FALSE, NULL), NULL); + } else if ((priv->audio_codec == GST_WFD_AUDIO_AAC) + || (priv->audio_codec == GST_WFD_AUDIO_AC3)) { + g_object_set (G_OBJECT (acaps), "caps", gst_caps_new_simple ("audio/x-raw", + "endianness", G_TYPE_INT, 1234, "signed", G_TYPE_BOOLEAN, TRUE, + "depth", G_TYPE_INT, 16, "rate", G_TYPE_INT, freq, "channels", + G_TYPE_INT, channels, NULL), NULL); + } + + if (priv->audio_codec == GST_WFD_AUDIO_AAC) { + acodec = g_strdup (priv->audio_encoder_aac); + is_enc_req = TRUE; + } else if (priv->audio_codec == GST_WFD_AUDIO_AC3) { + acodec = g_strdup (priv->audio_encoder_ac3); + is_enc_req = TRUE; + } else if (priv->audio_codec == GST_WFD_AUDIO_LPCM) { + GST_DEBUG_OBJECT (factory, "No codec required, raw data will be sent"); + is_enc_req = FALSE; + } else { + GST_ERROR_OBJECT (factory, "Yet to support other than H264 format"); + goto create_error; + } + + if (is_enc_req) { + aenc = gst_element_factory_make (acodec, "audioenc"); + if (NULL == aenc) { + GST_ERROR_OBJECT (factory, "failed to create audio encoder element"); + goto create_error; + } + + g_object_set (aenc, "compliance", -2, NULL); + g_object_set (aenc, "tolerance", 400000000, NULL); + g_object_set (aenc, "bitrate", (guint) 128000, NULL); + g_object_set (aenc, "rate-control", 2, NULL); + + aqueue = gst_element_factory_make ("queue", "audio-queue"); + if (!aqueue) { + GST_ERROR_OBJECT (factory, "failed to create audio queue element"); + goto create_error; + } + + gst_bin_add_many (srcbin, audiosrc, acaps, aenc, aqueue, NULL); + + if (!gst_element_link_many (audiosrc, acaps, aenc, aqueue, NULL)) { + GST_ERROR_OBJECT (factory, "Failed to link audio src elements..."); + goto create_error; + } + } else { + aqueue = gst_element_factory_make ("queue", "audio-queue"); + if (!aqueue) { + GST_ERROR_OBJECT (factory, "failed to create audio queue element"); + goto create_error; + } + + gst_bin_add_many (srcbin, audiosrc, acaps2, audio_convert, acaps, aqueue, NULL); + + if (!gst_element_link_many (audiosrc, acaps2, audio_convert, acaps, aqueue, NULL)) { + GST_ERROR_OBJECT (factory, "Failed to link audio src elements..."); + goto create_error; + } + } + + priv->audio_queue = aqueue; + if (acodec) g_free (acodec); + + return TRUE; + +create_error: + if (acodec) g_free (acodec); + return FALSE; +} + +static gboolean +_rtsp_media_factory_wfd_create_videotest_bin (GstRTSPMediaFactoryWFD * factory, + GstBin * srcbin) +{ + GstElement *videosrc = NULL; + GstElement *vcaps = NULL; + GstElement *videoconvert = NULL; + GstElement *venc_caps = NULL; + gchar *vcodec = NULL; + GstElement *venc = NULL; + GstElement *vparse = NULL; + GstElement *vqueue = NULL; + GstRTSPMediaFactoryWFDPrivate *priv = NULL; + + priv = factory->priv; + + GST_INFO_OBJECT (factory, "picked videotestsrc as video source"); + + videosrc = gst_element_factory_make ("videotestsrc", "videosrc"); + if (NULL == videosrc) { + GST_ERROR_OBJECT (factory, "failed to create ximagesrc element"); + goto create_error; + } + + /* create video caps element */ + vcaps = gst_element_factory_make ("capsfilter", "videocaps"); + if (NULL == vcaps) { + GST_ERROR_OBJECT (factory, "failed to create video capsilfter element"); + goto create_error; + } + + g_object_set (G_OBJECT (vcaps), "caps", + gst_caps_new_simple ("video/x-raw", + "format", G_TYPE_STRING, "I420", + "width", G_TYPE_INT, priv->video_width, + "height", G_TYPE_INT, priv->video_height, + "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL), + NULL); + + /* create video convert element */ + videoconvert = gst_element_factory_make ("videoconvert", "videoconvert"); + if (NULL == videoconvert) { + GST_ERROR_OBJECT (factory, "failed to create video videoconvert element"); + goto create_error; + } + + venc_caps = gst_element_factory_make ("capsfilter", "venc_caps"); + if (NULL == venc_caps) { + GST_ERROR_OBJECT (factory, "failed to create video capsilfter element"); + goto create_error; + } + + g_object_set (G_OBJECT (venc_caps), "caps", + gst_caps_new_simple ("video/x-raw", + "format", G_TYPE_STRING, "SN12", + "width", G_TYPE_INT, priv->video_width, + "height", G_TYPE_INT, priv->video_height, + "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL), + NULL); + + if (priv->video_codec == GST_WFD_VIDEO_H264) + vcodec = g_strdup (priv->video_encoder); + else { + GST_ERROR_OBJECT (factory, "Yet to support other than H264 format"); + goto create_error; + } + + venc = gst_element_factory_make (vcodec, "videoenc"); + if (vcodec) g_free (vcodec); + + if (!venc) { + GST_ERROR_OBJECT (factory, "failed to create video encoder element"); + goto create_error; + } + + g_object_set (venc, "aud", 0, NULL); + g_object_set (venc, "byte-stream", 1, NULL); + g_object_set (venc, "bitrate", 512, NULL); + + vparse = gst_element_factory_make ("h264parse", "videoparse"); + if (NULL == vparse) { + GST_ERROR_OBJECT (factory, "failed to create h264 parse element"); + goto create_error; + } + g_object_set (vparse, "config-interval", 1, NULL); + + vqueue = gst_element_factory_make ("queue", "video-queue"); + if (!vqueue) { + GST_ERROR_OBJECT (factory, "failed to create video queue element"); + goto create_error; + } + + gst_bin_add_many (srcbin, videosrc, vcaps, videoconvert, venc_caps, venc, vparse, vqueue, NULL); + if (!gst_element_link_many (videosrc, vcaps, videoconvert, venc_caps, venc, vparse, vqueue, NULL)) { + GST_ERROR_OBJECT (factory, "Failed to link video src elements..."); + goto create_error; + } + + priv->video_queue = vqueue; + + return TRUE; + +create_error: + return FALSE; +} + +static gboolean +_rtsp_media_factory_wfd_create_camera_capture_bin (GstRTSPMediaFactoryWFD * + factory, GstBin * srcbin) +{ + GstElement *videosrc = NULL; + GstElement *vcaps = NULL; + GstElement *venc = NULL; + GstElement *vparse = NULL; + GstElement *vqueue = NULL; + gchar *vcodec = NULL; + GstRTSPMediaFactoryWFDPrivate *priv = NULL; + + priv = factory->priv; + + videosrc = gst_element_factory_make ("camerasrc", "videosrc"); + if (NULL == videosrc) { + GST_ERROR_OBJECT (factory, "failed to create camerasrc element"); + goto create_error; + } + + /* create video caps element */ + vcaps = gst_element_factory_make ("capsfilter", "videocaps"); + if (NULL == vcaps) { + GST_ERROR_OBJECT (factory, "failed to create video capsilfter element"); + goto create_error; + } + + GST_INFO_OBJECT (factory, "picked camerasrc as video source"); + g_object_set (G_OBJECT (vcaps), "caps", + gst_caps_new_simple ("video/x-raw", + "width", G_TYPE_INT, priv->video_width, + "height", G_TYPE_INT, priv->video_height, + "format", G_TYPE_STRING, "SN12", + "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL), + NULL); + + if (priv->video_codec == GST_WFD_VIDEO_H264) + vcodec = g_strdup (priv->video_encoder); + else { + GST_ERROR_OBJECT (factory, "Yet to support other than H264 format"); + goto create_error; + } + + venc = gst_element_factory_make (vcodec, "videoenc"); + if (!venc) { + GST_ERROR_OBJECT (factory, "failed to create video encoder element"); + goto create_error; + } + if (vcodec) g_free (vcodec); + + g_object_set (venc, "bitrate", priv->video_bitrate, NULL); + g_object_set (venc, "byte-stream", 1, NULL); + g_object_set (venc, "append-dci", 1, NULL); + + vparse = gst_element_factory_make ("h264parse", "videoparse"); + if (NULL == vparse) { + GST_ERROR_OBJECT (factory, "failed to create h264 parse element"); + goto create_error; + } + g_object_set (vparse, "config-interval", 1, NULL); + + vqueue = gst_element_factory_make ("queue", "video-queue"); + if (!vqueue) { + GST_ERROR_OBJECT (factory, "failed to create video queue element"); + goto create_error; + } + + gst_bin_add_many (srcbin, videosrc, vcaps, venc, vparse, vqueue, NULL); + + if (!gst_element_link_many (videosrc, vcaps, venc, vparse, vqueue, NULL)) { + GST_ERROR_OBJECT (factory, "Failed to link video src elements..."); + goto create_error; + } + + priv->video_queue = vqueue; + + return TRUE; + +create_error: + return FALSE; +} + +static gboolean +_rtsp_media_factory_wfd_create_xcapture_bin (GstRTSPMediaFactoryWFD * factory, + GstBin * srcbin) +{ + GstElement *videosrc = NULL; + GstElement *vcaps = NULL; + GstElement *venc_caps = NULL; + GstElement *videoconvert = NULL, *videoscale = NULL; + gchar *vcodec = NULL; + GstElement *venc = NULL; + GstElement *vparse = NULL; + GstElement *vqueue = NULL; + GstRTSPMediaFactoryWFDPrivate *priv = NULL; + + priv = factory->priv; + + GST_INFO_OBJECT (factory, "picked ximagesrc as video source"); + + videosrc = gst_element_factory_make ("ximagesrc", "videosrc"); + if (NULL == videosrc) { + GST_ERROR_OBJECT (factory, "failed to create ximagesrc element"); + goto create_error; + } + + videoscale = gst_element_factory_make ("videoscale", "videoscale"); + if (NULL == videoscale) { + GST_ERROR_OBJECT (factory, "failed to create videoscale element"); + goto create_error; + } + + videoconvert = gst_element_factory_make ("videoconvert", "videoconvert"); + if (NULL == videoconvert) { + GST_ERROR_OBJECT (factory, "failed to create videoconvert element"); + goto create_error; + } + + /* create video caps element */ + vcaps = gst_element_factory_make ("capsfilter", "videocaps"); + if (NULL == vcaps) { + GST_ERROR_OBJECT (factory, "failed to create video capsilfter element"); + goto create_error; + } + + g_object_set (G_OBJECT (vcaps), "caps", + gst_caps_new_simple ("video/x-raw", + "width", G_TYPE_INT, priv->video_width, + "height", G_TYPE_INT, priv->video_height, + "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL), + NULL); + + if (priv->video_codec == GST_WFD_VIDEO_H264) + vcodec = g_strdup (priv->video_encoder); + else { + GST_ERROR_OBJECT (factory, "Yet to support other than H264 format"); + goto create_error; + } + + venc = gst_element_factory_make (vcodec, "videoenc"); + if (vcodec) g_free (vcodec); + + if (!venc) { + GST_ERROR_OBJECT (factory, "failed to create video encoder element"); + goto create_error; + } + + g_object_set (venc, "aud", 0, NULL); + g_object_set (venc, "byte-stream", 1, NULL); + g_object_set (venc, "bitrate", 512, NULL); + + venc_caps = gst_element_factory_make ("capsfilter", "venc_caps"); + if (NULL == venc_caps) { + GST_ERROR_OBJECT (factory, "failed to create video capsilfter element"); + goto create_error; + } + + g_object_set (G_OBJECT (venc_caps), "caps", + gst_caps_new_simple ("video/x-h264", + "profile", G_TYPE_STRING, "baseline", NULL), NULL); + + vparse = gst_element_factory_make ("h264parse", "videoparse"); + if (NULL == vparse) { + GST_ERROR_OBJECT (factory, "failed to create h264 parse element"); + goto create_error; + } + g_object_set (vparse, "config-interval", 1, NULL); + + vqueue = gst_element_factory_make ("queue", "video-queue"); + if (!vqueue) { + GST_ERROR_OBJECT (factory, "failed to create video queue element"); + goto create_error; + } + + gst_bin_add_many (srcbin, videosrc, videoscale, videoconvert, vcaps, venc, + venc_caps, vparse, vqueue, NULL); + if (!gst_element_link_many (videosrc, videoscale, videoconvert, vcaps, venc, + venc_caps, vparse, vqueue, NULL)) { + GST_ERROR_OBJECT (factory, "Failed to link video src elements..."); + goto create_error; + } + + priv->video_queue = vqueue; + + return TRUE; + +create_error: + return FALSE; +} + +static gboolean +_rtsp_media_factory_wfd_create_xvcapture_bin (GstRTSPMediaFactoryWFD * factory, + GstBin * srcbin) +{ + GstElement *videosrc = NULL; + GstElement *vcaps = NULL; + gchar *vcodec = NULL; + GstElement *venc = NULL; + GstElement *vparse = NULL; + GstElement *vqueue = NULL; + GstRTSPMediaFactoryWFDPrivate *priv = NULL; + + priv = factory->priv; + + GST_INFO_OBJECT (factory, "picked xvimagesrc as video source"); + + videosrc = gst_element_factory_make ("xvimagesrc", "videosrc"); + if (NULL == videosrc) { + GST_ERROR_OBJECT (factory, "failed to create xvimagesrc element"); + goto create_error; + } + + /* create video caps element */ + vcaps = gst_element_factory_make ("capsfilter", "videocaps"); + if (NULL == vcaps) { + GST_ERROR_OBJECT (factory, "failed to create video capsilfter element"); + goto create_error; + } + + g_object_set (G_OBJECT (vcaps), "caps", + gst_caps_new_simple ("video/x-raw", + "width", G_TYPE_INT, priv->video_width, + "height", G_TYPE_INT, priv->video_height, + "format", G_TYPE_STRING, "SN12", + "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL), + NULL); + + if (priv->video_codec == GST_WFD_VIDEO_H264) { + vcodec = g_strdup (priv->video_encoder); + } else { + GST_ERROR_OBJECT (factory, "Yet to support other than H264 format"); + goto create_error; + } + + venc = gst_element_factory_make (vcodec, "videoenc"); + if (!venc) { + GST_ERROR_OBJECT (factory, "failed to create video encoder element"); + goto create_error; + } + g_object_set (venc, "bitrate", priv->video_bitrate, NULL); + g_object_set (venc, "byte-stream", 1, NULL); + g_object_set (venc, "append-dci", 1, NULL); + g_object_set (venc, "idr-period", 120, NULL); + g_object_set (venc, "skip-inbuf", priv->video_enc_skip_inbuf_value, NULL); + + vparse = gst_element_factory_make ("h264parse", "videoparse"); + if (NULL == vparse) { + GST_ERROR_OBJECT (factory, "failed to create h264 parse element"); + goto create_error; + } + g_object_set (vparse, "config-interval", 1, NULL); + + vqueue = gst_element_factory_make ("queue", "video-queue"); + if (!vqueue) { + GST_ERROR_OBJECT (factory, "failed to create video queue element"); + goto create_error; + } + + gst_bin_add_many (srcbin, videosrc, vcaps, venc, vparse, vqueue, NULL); + if (!gst_element_link_many (videosrc, vcaps, venc, vparse, vqueue, NULL)) { + GST_ERROR_OBJECT (factory, "Failed to link video src elements..."); + goto create_error; + } + + priv->video_queue = vqueue; + if (vcodec) g_free (vcodec); + + return TRUE; + +create_error: + if (vcodec) g_free (vcodec); + return FALSE; +} + +static GstElement * +_rtsp_media_factory_wfd_create_srcbin (GstRTSPMediaFactoryWFD * factory) +{ + GstRTSPMediaFactoryWFDPrivate *priv = NULL; + + GstBin *srcbin = NULL; + GstElement *mux = NULL; + GstElement *mux_queue = NULL; + GstElement *payload = NULL; + GstPad *srcpad = NULL; + GstPad *mux_vsinkpad = NULL; + GstPad *mux_asinkpad = NULL; + + priv = factory->priv; + + /* create source bin */ + srcbin = GST_BIN (gst_bin_new ("srcbin")); + if (!srcbin) { + GST_ERROR_OBJECT (factory, "failed to create source bin..."); + goto create_error; + } + + /* create video src element */ + switch (priv->videosrc_type) { + case GST_WFD_VSRC_XIMAGESRC: + if (!_rtsp_media_factory_wfd_create_xcapture_bin (factory, srcbin)) { + GST_ERROR_OBJECT (factory, "failed to create xcapture bin..."); + goto create_error; + } + break; + case GST_WFD_VSRC_XVIMAGESRC: + if (!_rtsp_media_factory_wfd_create_xvcapture_bin (factory, srcbin)) { + GST_ERROR_OBJECT (factory, "failed to create xvcapture bin..."); + goto create_error; + } + break; + case GST_WFD_VSRC_CAMERASRC: + if (!_rtsp_media_factory_wfd_create_camera_capture_bin (factory, srcbin)) { + GST_ERROR_OBJECT (factory, "failed to create camera capture bin..."); + goto create_error; + } + break; + case GST_WFD_VSRC_VIDEOTESTSRC: + if (!_rtsp_media_factory_wfd_create_videotest_bin (factory, srcbin)) { + GST_ERROR_OBJECT (factory, "failed to create videotestsrc bin..."); + goto create_error; + } + break; + default: + GST_ERROR_OBJECT (factory, "unknow mode selected..."); + goto create_error; + } + + mux = gst_element_factory_make ("mpegtsmux", "tsmux"); + if (!mux) { + GST_ERROR_OBJECT (factory, "failed to create muxer element"); + goto create_error; + } + + g_object_set (mux, "wfd-mode", TRUE, NULL); + + mux_queue = gst_element_factory_make ("queue", "muxer-queue"); + if (!mux_queue) { + GST_ERROR_OBJECT (factory, "failed to create muxer-queue element"); + goto create_error; + } + + g_object_set (mux_queue, "max-size-buffers", 20000, NULL); + + payload = gst_element_factory_make ("rtpmp2tpay", "pay0"); + if (!payload) { + GST_ERROR_OBJECT (factory, "failed to create payload element"); + goto create_error; + } + + g_object_set (payload, "pt", 33, NULL); + g_object_set (payload, "mtu", priv->mtu_size, NULL); + g_object_set (payload, "rtp-flush", (gboolean) TRUE, NULL); + + gst_bin_add_many (srcbin, mux, mux_queue, payload, NULL); + + if (!gst_element_link_many (mux, mux_queue, payload, NULL)) { + GST_ERROR_OBJECT (factory, "Failed to link muxer & payload..."); + goto create_error; + } + + /* request video sink pad from muxer, which has elementary pid 0x1011 */ + mux_vsinkpad = gst_element_get_request_pad (mux, "sink_4113"); + if (!mux_vsinkpad) { + GST_ERROR_OBJECT (factory, "Failed to get sink pad from muxer..."); + goto create_error; + } + + /* request srcpad from video queue */ + srcpad = gst_element_get_static_pad (priv->video_queue, "src"); + if (!srcpad) { + GST_ERROR_OBJECT (factory, "Failed to get srcpad from video queue..."); + goto create_error; + } + + if (gst_pad_link (srcpad, mux_vsinkpad) != GST_PAD_LINK_OK) { + GST_ERROR_OBJECT (factory, + "Failed to link video queue src pad & muxer video sink pad..."); + goto create_error; + } + + gst_object_unref (mux_vsinkpad); + gst_object_unref (srcpad); + srcpad = NULL; + + /* create audio source elements & add to pipeline */ + if (!_rtsp_media_factory_wfd_create_audio_capture_bin (factory, srcbin)) + goto create_error; + + /* request audio sink pad from muxer, which has elementary pid 0x1100 */ + mux_asinkpad = gst_element_get_request_pad (mux, "sink_4352"); + if (!mux_asinkpad) { + GST_ERROR_OBJECT (factory, "Failed to get sinkpad from muxer..."); + goto create_error; + } + + /* request srcpad from audio queue */ + srcpad = gst_element_get_static_pad (priv->audio_queue, "src"); + if (!srcpad) { + GST_ERROR_OBJECT (factory, "Failed to get srcpad from audio queue..."); + goto create_error; + } + + /* link audio queue's srcpad & muxer sink pad */ + if (gst_pad_link (srcpad, mux_asinkpad) != GST_PAD_LINK_OK) { + GST_ERROR_OBJECT (factory, + "Failed to link audio queue src pad & muxer audio sink pad..."); + goto create_error; + } + gst_object_unref (mux_asinkpad); + gst_object_unref (srcpad); + + if (priv->dump_ts) + { + GstPad *pad_probe = NULL; + pad_probe = gst_element_get_static_pad (mux, "src"); + + if (NULL == pad_probe) { + GST_INFO_OBJECT (factory, "pad for probe not created"); + } else { + GST_INFO_OBJECT (factory, "pad for probe SUCCESSFUL"); + } + gst_pad_add_probe (pad_probe, GST_PAD_PROBE_TYPE_BUFFER, + rtsp_media_wfd_dump_data, factory, NULL); + } + + GST_DEBUG_OBJECT (factory, "successfully created source bin..."); + + return GST_ELEMENT_CAST (srcbin); + +create_error: + GST_ERROR_OBJECT (factory, "Failed to create pipeline"); + return NULL; +} + +static GstElement * +rtsp_media_factory_wfd_create_element (GstRTSPMediaFactory * factory, + const GstRTSPUrl * url) +{ + GstRTSPMediaFactoryWFD *_factory = GST_RTSP_MEDIA_FACTORY_WFD_CAST (factory); + GstElement *element = NULL; + + GST_RTSP_MEDIA_FACTORY_WFD_LOCK (factory); + + element = _rtsp_media_factory_wfd_create_srcbin (_factory); + + GST_RTSP_MEDIA_FACTORY_WFD_UNLOCK (factory); + + return element; +} + +static GstRTSPMedia * +rtsp_media_factory_wfd_construct (GstRTSPMediaFactory * factory, + const GstRTSPUrl * url) +{ + GstRTSPMedia *media; + GstElement *element, *pipeline; + GstRTSPMediaFactoryClass *klass; + + klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory); + + if (!klass->create_pipeline) + goto no_create; + + element = gst_rtsp_media_factory_create_element (factory, url); + if (element == NULL) + goto no_element; + + /* create a new empty media */ + media = gst_rtsp_media_new (element); + + gst_rtsp_media_collect_streams (media); + + pipeline = klass->create_pipeline (factory, media); + if (pipeline == NULL) + goto no_pipeline; + + return media; + + /* ERRORS */ +no_create: + { + g_critical ("no create_pipeline function"); + return NULL; + } +no_element: + { + g_critical ("could not create element"); + return NULL; + } +no_pipeline: + { + g_critical ("can't create pipeline"); + g_object_unref (media); + return NULL; + } +} diff --git a/gst/rtsp-server/rtsp-media-factory-wfd.h b/gst/rtsp-server/rtsp-media-factory-wfd.h new file mode 100644 index 0000000..5320d63 --- /dev/null +++ b/gst/rtsp-server/rtsp-media-factory-wfd.h @@ -0,0 +1,130 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include "rtsp-media-factory.h" + +#ifndef __GST_RTSP_MEDIA_FACTORY_WFD_H__ +#define __GST_RTSP_MEDIA_FACTORY_WFD_H__ + +G_BEGIN_DECLS +/* types for the media factory */ +#define GST_TYPE_RTSP_MEDIA_FACTORY_WFD (gst_rtsp_media_factory_wfd_get_type ()) +#define GST_IS_RTSP_MEDIA_FACTORY_WFD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_WFD)) +#define GST_IS_RTSP_MEDIA_FACTORY_WFD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_MEDIA_FACTORY_WFD)) +#define GST_RTSP_MEDIA_FACTORY_WFD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_WFD, GstRTSPMediaFactoryWFDClass)) +#define GST_RTSP_MEDIA_FACTORY_WFD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_WFD, GstRTSPMediaFactoryWFD)) +#define GST_RTSP_MEDIA_FACTORY_WFD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_MEDIA_FACTORY_WFD, GstRTSPMediaFactoryWFDClass)) +#define GST_RTSP_MEDIA_FACTORY_WFD_CAST(obj) ((GstRTSPMediaFactoryWFD*)(obj)) +#define GST_RTSP_MEDIA_FACTORY_WFD_CLASS_CAST(klass) ((GstRTSPMediaFactoryWFDClass*)(klass)) + enum +{ + GST_WFD_VSRC_XIMAGESRC, + GST_WFD_VSRC_XVIMAGESRC, + GST_WFD_VSRC_CAMERASRC, + GST_WFD_VSRC_VIDEOTESTSRC +}; + +typedef struct _GstRTSPMediaFactoryWFD GstRTSPMediaFactoryWFD; +typedef struct _GstRTSPMediaFactoryWFDClass GstRTSPMediaFactoryWFDClass; +typedef struct _GstRTSPMediaFactoryWFDPrivate GstRTSPMediaFactoryWFDPrivate; + +/** + * GstRTSPMediaFactoryWFD: + * + * The definition and logic for constructing the pipeline for a media. The media + * can contain multiple streams like audio and video. + */ +struct _GstRTSPMediaFactoryWFD +{ + GstRTSPMediaFactory parent; + + /*< private > */ + GstRTSPMediaFactoryWFDPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPMediaFactoryWFDClass: + * @gen_key: convert @url to a key for caching shared #GstRTSPMedia objects. + * The default implementation of this function will use the complete URL + * including the query parameters to return a key. + * @create_element: Construct and return a #GstElement that is a #GstBin containing + * the elements to use for streaming the media. The bin should contain + * payloaders pay\%d for each stream. The default implementation of this + * function returns the bin created from the launch parameter. + * @construct: the vmethod that will be called when the factory has to create the + * #GstRTSPMedia for @url. The default implementation of this + * function calls create_element to retrieve an element and then looks for + * pay\%d to create the streams. + * @create_pipeline: create a new pipeline or re-use an existing one and + * add the #GstRTSPMedia's element created by @construct to the pipeline. + * @configure: configure the media created with @construct. The default + * implementation will configure the 'shared' property of the media. + * @media_constructed: signal emited when a media was constructed + * @media_configure: signal emited when a media should be configured + * + * The #GstRTSPMediaFactoryWFD class structure. + */ +struct _GstRTSPMediaFactoryWFDClass +{ + GstRTSPMediaFactoryClass parent_class; + + gchar *(*gen_key) (GstRTSPMediaFactoryWFD * factory, const GstRTSPUrl * url); + + GstElement *(*create_element) (GstRTSPMediaFactoryWFD * factory, + const GstRTSPUrl * url); + GstRTSPMedia *(*construct) (GstRTSPMediaFactoryWFD * factory, + const GstRTSPUrl * url); + GstElement *(*create_pipeline) (GstRTSPMediaFactoryWFD * factory, + GstRTSPMedia * media); + void (*configure) (GstRTSPMediaFactoryWFD * factory, GstRTSPMedia * media); + + /* signals */ + void (*media_constructed) (GstRTSPMediaFactoryWFD * factory, + GstRTSPMedia * media); + void (*media_configure) (GstRTSPMediaFactoryWFD * factory, + GstRTSPMedia * media); + + /*< private > */ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +GType gst_rtsp_media_factory_wfd_get_type (void); + +/* creating the factory */ +GstRTSPMediaFactoryWFD *gst_rtsp_media_factory_wfd_new (void); +GstElement *gst_rtsp_media_factory_wfd_create_element (GstRTSPMediaFactoryWFD * + factory, const GstRTSPUrl * url); + +void gst_rtsp_media_factory_wfd_set (GstRTSPMediaFactoryWFD * factory, + guint8 videosrc_type, gchar *audio_device, guint64 audio_latency_time, + guint64 audio_buffer_time, gboolean audio_do_timestamp, guint mtu_size); +void gst_rtsp_media_factory_wfd_set_encoders (GstRTSPMediaFactoryWFD * factory, + gchar *video_encoder, gchar *audio_encoder_aac, gchar *audio_encoder_ac3); +void gst_rtsp_media_factory_wfd_set_dump_ts (GstRTSPMediaFactoryWFD * factory, + gboolean dump_ts); +void gst_rtsp_media_factory_wfd_set_negotiated_resolution (GstRTSPMediaFactory *factory, + guint32 width, guint32 height); +void gst_rtsp_media_factory_wfd_set_audio_codec (GstRTSPMediaFactory *factory, + guint audio_codec); + +G_END_DECLS +#endif /* __GST_RTSP_MEDIA_FACTORY_WFD_H__ */ diff --git a/gst/rtsp-server/rtsp-media-factory.c b/gst/rtsp-server/rtsp-media-factory.c new file mode 100644 index 0000000..7d85dcc --- /dev/null +++ b/gst/rtsp-server/rtsp-media-factory.c @@ -0,0 +1,1147 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-media-factory + * @short_description: A factory for media pipelines + * @see_also: #GstRTSPMountPoints, #GstRTSPMedia + * + * The #GstRTSPMediaFactory is responsible for creating or recycling + * #GstRTSPMedia objects based on the passed URL. + * + * The default implementation of the object can create #GstRTSPMedia objects + * containing a pipeline created from a launch description set with + * gst_rtsp_media_factory_set_launch(). + * + * Media from a factory can be shared by setting the shared flag with + * gst_rtsp_media_factory_set_shared(). When a factory is shared, + * gst_rtsp_media_factory_construct() will return the same #GstRTSPMedia when + * the url matches. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include "rtsp-media-factory.h" + +#define GST_RTSP_MEDIA_FACTORY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY, GstRTSPMediaFactoryPrivate)) + +#define GST_RTSP_MEDIA_FACTORY_GET_LOCK(f) (&(GST_RTSP_MEDIA_FACTORY_CAST(f)->priv->lock)) +#define GST_RTSP_MEDIA_FACTORY_LOCK(f) (g_mutex_lock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f))) +#define GST_RTSP_MEDIA_FACTORY_UNLOCK(f) (g_mutex_unlock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f))) + +struct _GstRTSPMediaFactoryPrivate +{ + GMutex lock; /* protects everything but medias */ + GstRTSPPermissions *permissions; + gchar *launch; + gboolean shared; + GstRTSPSuspendMode suspend_mode; + gboolean eos_shutdown; + GstRTSPProfile profiles; + GstRTSPLowerTrans protocols; + guint buffer_size; + GstRTSPAddressPool *pool; + + GMutex medias_lock; + GHashTable *medias; /* protected by medias_lock */ +}; + +#define DEFAULT_LAUNCH NULL +#define DEFAULT_SHARED FALSE +#define DEFAULT_SUSPEND_MODE GST_RTSP_SUSPEND_MODE_NONE +#define DEFAULT_EOS_SHUTDOWN FALSE +#define DEFAULT_PROFILES GST_RTSP_PROFILE_AVP +#define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \ + GST_RTSP_LOWER_TRANS_TCP +#define DEFAULT_BUFFER_SIZE 0x80000 + +enum +{ + PROP_0, + PROP_LAUNCH, + PROP_SHARED, + PROP_SUSPEND_MODE, + PROP_EOS_SHUTDOWN, + PROP_PROFILES, + PROP_PROTOCOLS, + PROP_BUFFER_SIZE, + PROP_LAST +}; + +enum +{ + SIGNAL_MEDIA_CONSTRUCTED, + SIGNAL_MEDIA_CONFIGURE, + SIGNAL_LAST +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug); +#define GST_CAT_DEFAULT rtsp_media_debug + +static guint gst_rtsp_media_factory_signals[SIGNAL_LAST] = { 0 }; + +static void gst_rtsp_media_factory_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_media_factory_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); +static void gst_rtsp_media_factory_finalize (GObject * obj); + +static gchar *default_gen_key (GstRTSPMediaFactory * factory, + const GstRTSPUrl * url); +static GstElement *default_create_element (GstRTSPMediaFactory * factory, + const GstRTSPUrl * url); +static GstRTSPMedia *default_construct (GstRTSPMediaFactory * factory, + const GstRTSPUrl * url); +static void default_configure (GstRTSPMediaFactory * factory, + GstRTSPMedia * media); +static GstElement *default_create_pipeline (GstRTSPMediaFactory * factory, + GstRTSPMedia * media); + +G_DEFINE_TYPE (GstRTSPMediaFactory, gst_rtsp_media_factory, G_TYPE_OBJECT); + +static void +gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPMediaFactoryPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gst_rtsp_media_factory_get_property; + gobject_class->set_property = gst_rtsp_media_factory_set_property; + gobject_class->finalize = gst_rtsp_media_factory_finalize; + + /** + * GstRTSPMediaFactory::launch: + * + * The gst_parse_launch() line to use for constructing the pipeline in the + * default prepare vmethod. + * + * The pipeline description should return a GstBin as the toplevel element + * which can be accomplished by enclosing the dscription with brackets '(' + * ')'. + * + * The description should return a pipeline with payloaders named pay0, pay1, + * etc.. Each of the payloaders will result in a stream. + * + * Support for dynamic payloaders can be accomplished by adding payloaders + * named dynpay0, dynpay1, etc.. + */ + g_object_class_install_property (gobject_class, PROP_LAUNCH, + g_param_spec_string ("launch", "Launch", + "A launch description of the pipeline", DEFAULT_LAUNCH, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_SHARED, + g_param_spec_boolean ("shared", "Shared", + "If media from this factory is shared", DEFAULT_SHARED, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_SUSPEND_MODE, + g_param_spec_enum ("suspend-mode", "Suspend Mode", + "Control how media will be suspended", GST_TYPE_RTSP_SUSPEND_MODE, + DEFAULT_SUSPEND_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN, + g_param_spec_boolean ("eos-shutdown", "EOS Shutdown", + "Send EOS down the pipeline before shutting down", + DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_PROFILES, + g_param_spec_flags ("profiles", "Profiles", + "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE, + DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_PROTOCOLS, + g_param_spec_flags ("protocols", "Protocols", + "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS, + DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE, + g_param_spec_uint ("buffer-size", "Buffer Size", + "The kernel UDP buffer size to use", 0, G_MAXUINT, + DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONSTRUCTED] = + g_signal_new ("media-constructed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaFactoryClass, + media_constructed), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_RTSP_MEDIA); + + gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONFIGURE] = + g_signal_new ("media-configure", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaFactoryClass, + media_configure), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_RTSP_MEDIA); + + klass->gen_key = default_gen_key; + klass->create_element = default_create_element; + klass->construct = default_construct; + klass->configure = default_configure; + klass->create_pipeline = default_create_pipeline; + + GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmediafactory", 0, + "GstRTSPMediaFactory"); +} + +static void +gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory) +{ + GstRTSPMediaFactoryPrivate *priv = + GST_RTSP_MEDIA_FACTORY_GET_PRIVATE (factory); + factory->priv = priv; + + priv->launch = g_strdup (DEFAULT_LAUNCH); + priv->shared = DEFAULT_SHARED; + priv->suspend_mode = DEFAULT_SUSPEND_MODE; + priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN; + priv->profiles = DEFAULT_PROFILES; + priv->protocols = DEFAULT_PROTOCOLS; + priv->buffer_size = DEFAULT_BUFFER_SIZE; + + g_mutex_init (&priv->lock); + g_mutex_init (&priv->medias_lock); + priv->medias = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_object_unref); +} + +static void +gst_rtsp_media_factory_finalize (GObject * obj) +{ + GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (obj); + GstRTSPMediaFactoryPrivate *priv = factory->priv; + + if (priv->permissions) + gst_rtsp_permissions_unref (priv->permissions); + g_hash_table_unref (priv->medias); + g_mutex_clear (&priv->medias_lock); + g_free (priv->launch); + g_mutex_clear (&priv->lock); + if (priv->pool) + g_object_unref (priv->pool); + + G_OBJECT_CLASS (gst_rtsp_media_factory_parent_class)->finalize (obj); +} + +static void +gst_rtsp_media_factory_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (object); + + switch (propid) { + case PROP_LAUNCH: + g_value_take_string (value, gst_rtsp_media_factory_get_launch (factory)); + break; + case PROP_SHARED: + g_value_set_boolean (value, gst_rtsp_media_factory_is_shared (factory)); + break; + case PROP_SUSPEND_MODE: + g_value_set_enum (value, + gst_rtsp_media_factory_get_suspend_mode (factory)); + break; + case PROP_EOS_SHUTDOWN: + g_value_set_boolean (value, + gst_rtsp_media_factory_is_eos_shutdown (factory)); + break; + case PROP_PROFILES: + g_value_set_flags (value, gst_rtsp_media_factory_get_profiles (factory)); + break; + case PROP_PROTOCOLS: + g_value_set_flags (value, gst_rtsp_media_factory_get_protocols (factory)); + break; + case PROP_BUFFER_SIZE: + g_value_set_uint (value, + gst_rtsp_media_factory_get_buffer_size (factory)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_media_factory_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (object); + + switch (propid) { + case PROP_LAUNCH: + gst_rtsp_media_factory_set_launch (factory, g_value_get_string (value)); + break; + case PROP_SHARED: + gst_rtsp_media_factory_set_shared (factory, g_value_get_boolean (value)); + break; + case PROP_SUSPEND_MODE: + gst_rtsp_media_factory_set_suspend_mode (factory, + g_value_get_enum (value)); + break; + case PROP_EOS_SHUTDOWN: + gst_rtsp_media_factory_set_eos_shutdown (factory, + g_value_get_boolean (value)); + break; + case PROP_PROFILES: + gst_rtsp_media_factory_set_profiles (factory, g_value_get_flags (value)); + break; + case PROP_PROTOCOLS: + gst_rtsp_media_factory_set_protocols (factory, g_value_get_flags (value)); + break; + case PROP_BUFFER_SIZE: + gst_rtsp_media_factory_set_buffer_size (factory, + g_value_get_uint (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +/** + * gst_rtsp_media_factory_new: + * + * Create a new #GstRTSPMediaFactory instance. + * + * Returns: (transfer full): a new #GstRTSPMediaFactory object. + */ +GstRTSPMediaFactory * +gst_rtsp_media_factory_new (void) +{ + GstRTSPMediaFactory *result; + + result = g_object_new (GST_TYPE_RTSP_MEDIA_FACTORY, NULL); + + return result; +} + +/** + * gst_rtsp_media_factory_set_permissions: + * @factory: a #GstRTSPMediaFactory + * @permissions: (transfer none): a #GstRTSPPermissions + * + * Set @permissions on @factory. + */ +void +gst_rtsp_media_factory_set_permissions (GstRTSPMediaFactory * factory, + GstRTSPPermissions * permissions) +{ + GstRTSPMediaFactoryPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + if (priv->permissions) + gst_rtsp_permissions_unref (priv->permissions); + if ((priv->permissions = permissions)) + gst_rtsp_permissions_ref (permissions); + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); +} + +/** + * gst_rtsp_media_factory_get_permissions: + * @factory: a #GstRTSPMediaFactory + * + * Get the permissions object from @factory. + * + * Returns: (transfer full): a #GstRTSPPermissions object, unref after usage. + */ +GstRTSPPermissions * +gst_rtsp_media_factory_get_permissions (GstRTSPMediaFactory * factory) +{ + GstRTSPMediaFactoryPrivate *priv; + GstRTSPPermissions *result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + if ((result = priv->permissions)) + gst_rtsp_permissions_ref (result); + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + return result; +} + +/** + * gst_rtsp_media_factory_add_role: + * @factory: a #GstRTSPMediaFactory + * @role: a role + * @fieldname: the first field name + * @...: additional arguments + * + * A convenience method to add @role with @fieldname and additional arguments to + * the permissions of @factory. If @factory had no permissions, new permissions + * will be created and the role will be added to it. + */ +void +gst_rtsp_media_factory_add_role (GstRTSPMediaFactory * factory, + const gchar * role, const gchar * fieldname, ...) +{ + GstRTSPMediaFactoryPrivate *priv; + va_list var_args; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + g_return_if_fail (role != NULL); + g_return_if_fail (fieldname != NULL); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + if (priv->permissions == NULL) + priv->permissions = gst_rtsp_permissions_new (); + + va_start (var_args, fieldname); + gst_rtsp_permissions_add_role_valist (priv->permissions, role, fieldname, + var_args); + va_end (var_args); + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); +} + +/** + * gst_rtsp_media_factory_set_launch: + * @factory: a #GstRTSPMediaFactory + * @launch: the launch description + * + * + * The gst_parse_launch() line to use for constructing the pipeline in the + * default prepare vmethod. + * + * The pipeline description should return a GstBin as the toplevel element + * which can be accomplished by enclosing the dscription with brackets '(' + * ')'. + * + * The description should return a pipeline with payloaders named pay0, pay1, + * etc.. Each of the payloaders will result in a stream. + */ +void +gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory * factory, + const gchar * launch) +{ + GstRTSPMediaFactoryPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + g_return_if_fail (launch != NULL); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + g_free (priv->launch); + priv->launch = g_strdup (launch); + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); +} + +/** + * gst_rtsp_media_factory_get_launch: + * @factory: a #GstRTSPMediaFactory + * + * Get the gst_parse_launch() pipeline description that will be used in the + * default prepare vmethod. + * + * Returns: (transfer full): the configured launch description. g_free() after + * usage. + */ +gchar * +gst_rtsp_media_factory_get_launch (GstRTSPMediaFactory * factory) +{ + GstRTSPMediaFactoryPrivate *priv; + gchar *result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + result = g_strdup (priv->launch); + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + return result; +} + +/** + * gst_rtsp_media_factory_set_suspend_mode: + * @factory: a #GstRTSPMediaFactory + * @mode: the new #GstRTSPSuspendMode + * + * Configure how media created from this factory will be suspended. + */ +void +gst_rtsp_media_factory_set_suspend_mode (GstRTSPMediaFactory * factory, + GstRTSPSuspendMode mode) +{ + GstRTSPMediaFactoryPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + priv->suspend_mode = mode; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); +} + +/** + * gst_rtsp_media_factory_get_suspend_mode: + * @factory: a #GstRTSPMediaFactory + * + * Get how media created from this factory will be suspended. + * + * Returns: a #GstRTSPSuspendMode. + */ +GstRTSPSuspendMode +gst_rtsp_media_factory_get_suspend_mode (GstRTSPMediaFactory * factory) +{ + GstRTSPMediaFactoryPrivate *priv; + GstRTSPSuspendMode result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), + GST_RTSP_SUSPEND_MODE_NONE); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + result = priv->suspend_mode; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + return result; +} + +/** + * gst_rtsp_media_factory_set_shared: + * @factory: a #GstRTSPMediaFactory + * @shared: the new value + * + * Configure if media created from this factory can be shared between clients. + */ +void +gst_rtsp_media_factory_set_shared (GstRTSPMediaFactory * factory, + gboolean shared) +{ + GstRTSPMediaFactoryPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + priv->shared = shared; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); +} + +/** + * gst_rtsp_media_factory_is_shared: + * @factory: a #GstRTSPMediaFactory + * + * Get if media created from this factory can be shared between clients. + * + * Returns: %TRUE if the media will be shared between clients. + */ +gboolean +gst_rtsp_media_factory_is_shared (GstRTSPMediaFactory * factory) +{ + GstRTSPMediaFactoryPrivate *priv; + gboolean result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + result = priv->shared; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + return result; +} + +/** + * gst_rtsp_media_factory_set_eos_shutdown: + * @factory: a #GstRTSPMediaFactory + * @eos_shutdown: the new value + * + * Configure if media created from this factory will have an EOS sent to the + * pipeline before shutdown. + */ +void +gst_rtsp_media_factory_set_eos_shutdown (GstRTSPMediaFactory * factory, + gboolean eos_shutdown) +{ + GstRTSPMediaFactoryPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + priv->eos_shutdown = eos_shutdown; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); +} + +/** + * gst_rtsp_media_factory_is_eos_shutdown: + * @factory: a #GstRTSPMediaFactory + * + * Get if media created from this factory will have an EOS event sent to the + * pipeline before shutdown. + * + * Returns: %TRUE if the media will receive EOS before shutdown. + */ +gboolean +gst_rtsp_media_factory_is_eos_shutdown (GstRTSPMediaFactory * factory) +{ + GstRTSPMediaFactoryPrivate *priv; + gboolean result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + result = priv->eos_shutdown; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + return result; +} + +/** + * gst_rtsp_media_factory_set_buffer_size: + * @factory: a #GstRTSPMedia + * @size: the new value + * + * Set the kernel UDP buffer size. + */ +void +gst_rtsp_media_factory_set_buffer_size (GstRTSPMediaFactory * factory, + guint size) +{ + GstRTSPMediaFactoryPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + priv->buffer_size = size; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); +} + +/** + * gst_rtsp_media_factory_get_buffer_size: + * @factory: a #GstRTSPMedia + * + * Get the kernel UDP buffer size. + * + * Returns: the kernel UDP buffer size. + */ +guint +gst_rtsp_media_factory_get_buffer_size (GstRTSPMediaFactory * factory) +{ + GstRTSPMediaFactoryPrivate *priv; + guint result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + result = priv->buffer_size; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + return result; +} + +/** + * gst_rtsp_media_factory_set_address_pool: + * @factory: a #GstRTSPMediaFactory + * @pool: (transfer none): a #GstRTSPAddressPool + * + * configure @pool to be used as the address pool of @factory. + */ +void +gst_rtsp_media_factory_set_address_pool (GstRTSPMediaFactory * factory, + GstRTSPAddressPool * pool) +{ + GstRTSPMediaFactoryPrivate *priv; + GstRTSPAddressPool *old; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + if ((old = priv->pool) != pool) + priv->pool = pool ? g_object_ref (pool) : NULL; + else + old = NULL; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + if (old) + g_object_unref (old); +} + +/** + * gst_rtsp_media_factory_get_address_pool: + * @factory: a #GstRTSPMediaFactory + * + * Get the #GstRTSPAddressPool used as the address pool of @factory. + * + * Returns: (transfer full): the #GstRTSPAddressPool of @factory. g_object_unref() after + * usage. + */ +GstRTSPAddressPool * +gst_rtsp_media_factory_get_address_pool (GstRTSPMediaFactory * factory) +{ + GstRTSPMediaFactoryPrivate *priv; + GstRTSPAddressPool *result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + if ((result = priv->pool)) + g_object_ref (result); + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + return result; +} + +/** + * gst_rtsp_media_factory_set_profiles: + * @factory: a #GstRTSPMediaFactory + * @profiles: the new flags + * + * Configure the allowed profiles for @factory. + */ +void +gst_rtsp_media_factory_set_profiles (GstRTSPMediaFactory * factory, + GstRTSPProfile profiles) +{ + GstRTSPMediaFactoryPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + + priv = factory->priv; + + GST_DEBUG_OBJECT (factory, "profiles %d", profiles); + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + priv->profiles = profiles; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); +} + +/** + * gst_rtsp_media_factory_get_profiles: + * @factory: a #GstRTSPMediaFactory + * + * Get the allowed profiles of @factory. + * + * Returns: a #GstRTSPProfile + */ +GstRTSPProfile +gst_rtsp_media_factory_get_profiles (GstRTSPMediaFactory * factory) +{ + GstRTSPMediaFactoryPrivate *priv; + GstRTSPProfile res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), + GST_RTSP_PROFILE_UNKNOWN); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + res = priv->profiles; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + return res; +} + +/** + * gst_rtsp_media_factory_set_protocols: + * @factory: a #GstRTSPMediaFactory + * @protocols: the new flags + * + * Configure the allowed lower transport for @factory. + */ +void +gst_rtsp_media_factory_set_protocols (GstRTSPMediaFactory * factory, + GstRTSPLowerTrans protocols) +{ + GstRTSPMediaFactoryPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + + priv = factory->priv; + + GST_DEBUG_OBJECT (factory, "protocols %d", protocols); + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + priv->protocols = protocols; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); +} + +/** + * gst_rtsp_media_factory_get_protocols: + * @factory: a #GstRTSPMediaFactory + * + * Get the allowed protocols of @factory. + * + * Returns: a #GstRTSPLowerTrans + */ +GstRTSPLowerTrans +gst_rtsp_media_factory_get_protocols (GstRTSPMediaFactory * factory) +{ + GstRTSPMediaFactoryPrivate *priv; + GstRTSPLowerTrans res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), + GST_RTSP_LOWER_TRANS_UNKNOWN); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + res = priv->protocols; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + return res; +} + +static gboolean +compare_media (gpointer key, GstRTSPMedia * media1, GstRTSPMedia * media2) +{ + return (media1 == media2); +} + +static void +media_unprepared (GstRTSPMedia * media, GWeakRef * ref) +{ + GstRTSPMediaFactory *factory = g_weak_ref_get (ref); + GstRTSPMediaFactoryPrivate *priv; + + if (!factory) + return; + + priv = factory->priv;; + + g_mutex_lock (&priv->medias_lock); + g_hash_table_foreach_remove (priv->medias, (GHRFunc) compare_media, media); + g_mutex_unlock (&priv->medias_lock); + + g_object_unref (factory); +} + +static GWeakRef * +weak_ref_new (gpointer obj) +{ + GWeakRef *ref = g_slice_new (GWeakRef); + + g_weak_ref_init (ref, obj); + return ref; +} + +static void +weak_ref_free (GWeakRef * ref) +{ + g_weak_ref_clear (ref); + g_slice_free (GWeakRef, ref); +} + +/** + * gst_rtsp_media_factory_construct: + * @factory: a #GstRTSPMediaFactory + * @url: the url used + * + * Construct the media object and create its streams. Implementations + * should create the needed gstreamer elements and add them to the result + * object. No state changes should be performed on them yet. + * + * One or more GstRTSPStream objects should be created from the result + * with gst_rtsp_media_create_stream (). + * + * After the media is constructed, it can be configured and then prepared + * with gst_rtsp_media_prepare (). + * + * Returns: (transfer full): a new #GstRTSPMedia if the media could be prepared. + */ +GstRTSPMedia * +gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory, + const GstRTSPUrl * url) +{ + GstRTSPMediaFactoryPrivate *priv; + gchar *key; + GstRTSPMedia *media; + GstRTSPMediaFactoryClass *klass; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL); + g_return_val_if_fail (url != NULL, NULL); + + priv = factory->priv;; + klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory); + + /* convert the url to a key for the hashtable. NULL return or a NULL function + * will not cache anything for this factory. */ + if (klass->gen_key) + key = klass->gen_key (factory, url); + else + key = NULL; + + g_mutex_lock (&priv->medias_lock); + if (key) { + /* we have a key, see if we find a cached media */ + media = g_hash_table_lookup (priv->medias, key); + if (media) + g_object_ref (media); + } else + media = NULL; + + if (media == NULL) { + /* nothing cached found, try to create one */ + if (klass->construct) { + media = klass->construct (factory, url); + if (media) + g_signal_emit (factory, + gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONSTRUCTED], 0, media, + NULL); + } else + media = NULL; + + if (media) { + /* configure the media */ + if (klass->configure) + klass->configure (factory, media); + + g_signal_emit (factory, + gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONFIGURE], 0, media, + NULL); + + /* check if we can cache this media */ + if (gst_rtsp_media_is_shared (media)) { + /* insert in the hashtable, takes ownership of the key */ + g_object_ref (media); + g_hash_table_insert (priv->medias, key, media); + key = NULL; + } + if (!gst_rtsp_media_is_reusable (media)) { + /* when not reusable, connect to the unprepare signal to remove the item + * from our cache when it gets unprepared */ + g_signal_connect_data (media, "unprepared", + (GCallback) media_unprepared, weak_ref_new (factory), + (GClosureNotify) weak_ref_free, 0); + } + } + } + g_mutex_unlock (&priv->medias_lock); + + if (key) + g_free (key); + + GST_INFO ("constructed media %p for url %s", media, url->abspath); + + return media; +} + +static gchar * +default_gen_key (GstRTSPMediaFactory * factory, const GstRTSPUrl * url) +{ + gchar *result; + const gchar *pre_query; + const gchar *query; + + pre_query = url->query ? "?" : ""; + query = url->query ? url->query : ""; + + result = + g_strdup_printf ("%u%s%s%s", url->port, url->abspath, pre_query, query); + + return result; +} + +static GstElement * +default_create_element (GstRTSPMediaFactory * factory, const GstRTSPUrl * url) +{ + GstRTSPMediaFactoryPrivate *priv = factory->priv; + GstElement *element; + GError *error = NULL; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + /* we need a parse syntax */ + if (priv->launch == NULL) + goto no_launch; + + /* parse the user provided launch line */ + element = gst_parse_launch (priv->launch, &error); + if (element == NULL) + goto parse_error; + + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + if (error != NULL) { + /* a recoverable error was encountered */ + GST_WARNING ("recoverable parsing error: %s", error->message); + g_error_free (error); + } + return element; + + /* ERRORS */ +no_launch: + { + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + g_critical ("no launch line specified"); + return NULL; + } +parse_error: + { + g_critical ("could not parse launch syntax (%s): %s", priv->launch, + (error ? error->message : "unknown reason")); + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + if (error) + g_error_free (error); + return NULL; + } +} + +static GstRTSPMedia * +default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url) +{ + GstRTSPMedia *media; + GstElement *element, *pipeline; + GstRTSPMediaFactoryClass *klass; + + klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory); + + if (!klass->create_pipeline) + goto no_create; + + element = gst_rtsp_media_factory_create_element (factory, url); + if (element == NULL) + goto no_element; + + /* create a new empty media */ + media = gst_rtsp_media_new (element); + + gst_rtsp_media_collect_streams (media); + + pipeline = klass->create_pipeline (factory, media); + if (pipeline == NULL) + goto no_pipeline; + + return media; + + /* ERRORS */ +no_create: + { + g_critical ("no create_pipeline function"); + return NULL; + } +no_element: + { + g_critical ("could not create element"); + return NULL; + } +no_pipeline: + { + g_critical ("can't create pipeline"); + g_object_unref (media); + return NULL; + } +} + +static GstElement * +default_create_pipeline (GstRTSPMediaFactory * factory, GstRTSPMedia * media) +{ + GstElement *pipeline; + + pipeline = gst_pipeline_new ("media-pipeline"); + gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline)); + + return pipeline; +} + +static void +default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media) +{ + GstRTSPMediaFactoryPrivate *priv = factory->priv; + gboolean shared, eos_shutdown; + guint size; + GstRTSPSuspendMode suspend_mode; + GstRTSPProfile profiles; + GstRTSPLowerTrans protocols; + GstRTSPAddressPool *pool; + GstRTSPPermissions *perms; + + /* configure the sharedness */ + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + suspend_mode = priv->suspend_mode; + shared = priv->shared; + eos_shutdown = priv->eos_shutdown; + size = priv->buffer_size; + profiles = priv->profiles; + protocols = priv->protocols; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + gst_rtsp_media_set_suspend_mode (media, suspend_mode); + gst_rtsp_media_set_shared (media, shared); + gst_rtsp_media_set_eos_shutdown (media, eos_shutdown); + gst_rtsp_media_set_buffer_size (media, size); + gst_rtsp_media_set_profiles (media, profiles); + gst_rtsp_media_set_protocols (media, protocols); + + if ((pool = gst_rtsp_media_factory_get_address_pool (factory))) { + gst_rtsp_media_set_address_pool (media, pool); + g_object_unref (pool); + } + if ((perms = gst_rtsp_media_factory_get_permissions (factory))) { + gst_rtsp_media_set_permissions (media, perms); + gst_rtsp_permissions_unref (perms); + } +} + +/** + * gst_rtsp_media_factory_create_element: + * @factory: a #GstRTSPMediaFactory + * @url: the url used + * + * Construct and return a #GstElement that is a #GstBin containing + * the elements to use for streaming the media. + * + * The bin should contain payloaders pay\%d for each stream. The default + * implementation of this function returns the bin created from the + * launch parameter. + * + * Returns: (transfer floating): a new #GstElement. + */ +GstElement * +gst_rtsp_media_factory_create_element (GstRTSPMediaFactory * factory, + const GstRTSPUrl * url) +{ + GstRTSPMediaFactoryClass *klass; + GstElement *result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL); + g_return_val_if_fail (url != NULL, NULL); + + klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory); + + if (klass->create_element) + result = klass->create_element (factory, url); + else + result = NULL; + + return result; +} diff --git a/gst/rtsp-server/rtsp-media-factory.h b/gst/rtsp-server/rtsp-media-factory.h new file mode 100644 index 0000000..bb6aec3 --- /dev/null +++ b/gst/rtsp-server/rtsp-media-factory.h @@ -0,0 +1,154 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include +#include + +#include "rtsp-media.h" +#include "rtsp-permissions.h" +#include "rtsp-address-pool.h" + +#ifndef __GST_RTSP_MEDIA_FACTORY_H__ +#define __GST_RTSP_MEDIA_FACTORY_H__ + +G_BEGIN_DECLS + +/* types for the media factory */ +#define GST_TYPE_RTSP_MEDIA_FACTORY (gst_rtsp_media_factory_get_type ()) +#define GST_IS_RTSP_MEDIA_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY)) +#define GST_IS_RTSP_MEDIA_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_MEDIA_FACTORY)) +#define GST_RTSP_MEDIA_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_MEDIA_FACTORY, GstRTSPMediaFactoryClass)) +#define GST_RTSP_MEDIA_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_MEDIA_FACTORY, GstRTSPMediaFactory)) +#define GST_RTSP_MEDIA_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_MEDIA_FACTORY, GstRTSPMediaFactoryClass)) +#define GST_RTSP_MEDIA_FACTORY_CAST(obj) ((GstRTSPMediaFactory*)(obj)) +#define GST_RTSP_MEDIA_FACTORY_CLASS_CAST(klass) ((GstRTSPMediaFactoryClass*)(klass)) + +typedef struct _GstRTSPMediaFactory GstRTSPMediaFactory; +typedef struct _GstRTSPMediaFactoryClass GstRTSPMediaFactoryClass; +typedef struct _GstRTSPMediaFactoryPrivate GstRTSPMediaFactoryPrivate; + +/** + * GstRTSPMediaFactory: + * + * The definition and logic for constructing the pipeline for a media. The media + * can contain multiple streams like audio and video. + */ +struct _GstRTSPMediaFactory { + GObject parent; + + /*< private >*/ + GstRTSPMediaFactoryPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPMediaFactoryClass: + * @gen_key: convert @url to a key for caching shared #GstRTSPMedia objects. + * The default implementation of this function will use the complete URL + * including the query parameters to return a key. + * @create_element: Construct and return a #GstElement that is a #GstBin containing + * the elements to use for streaming the media. The bin should contain + * payloaders pay\%d for each stream. The default implementation of this + * function returns the bin created from the launch parameter. + * @construct: the vmethod that will be called when the factory has to create the + * #GstRTSPMedia for @url. The default implementation of this + * function calls create_element to retrieve an element and then looks for + * pay\%d to create the streams. + * @create_pipeline: create a new pipeline or re-use an existing one and + * add the #GstRTSPMedia's element created by @construct to the pipeline. + * @configure: configure the media created with @construct. The default + * implementation will configure the 'shared' property of the media. + * @media_constructed: signal emited when a media was constructed + * @media_configure: signal emited when a media should be configured + * + * The #GstRTSPMediaFactory class structure. + */ +struct _GstRTSPMediaFactoryClass { + GObjectClass parent_class; + + gchar * (*gen_key) (GstRTSPMediaFactory *factory, const GstRTSPUrl *url); + + GstElement * (*create_element) (GstRTSPMediaFactory *factory, const GstRTSPUrl *url); + GstRTSPMedia * (*construct) (GstRTSPMediaFactory *factory, const GstRTSPUrl *url); + GstElement * (*create_pipeline) (GstRTSPMediaFactory *factory, GstRTSPMedia *media); + void (*configure) (GstRTSPMediaFactory *factory, GstRTSPMedia *media); + + /* signals */ + void (*media_constructed) (GstRTSPMediaFactory *factory, GstRTSPMedia *media); + void (*media_configure) (GstRTSPMediaFactory *factory, GstRTSPMedia *media); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +GType gst_rtsp_media_factory_get_type (void); + +/* creating the factory */ +GstRTSPMediaFactory * gst_rtsp_media_factory_new (void); + +/* configuring the factory */ +void gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory *factory, + const gchar *launch); +gchar * gst_rtsp_media_factory_get_launch (GstRTSPMediaFactory *factory); + +void gst_rtsp_media_factory_set_permissions (GstRTSPMediaFactory *factory, + GstRTSPPermissions *permissions); +GstRTSPPermissions * gst_rtsp_media_factory_get_permissions (GstRTSPMediaFactory *factory); +void gst_rtsp_media_factory_add_role (GstRTSPMediaFactory *factory, + const gchar *role, + const gchar *fieldname, ...); + +void gst_rtsp_media_factory_set_shared (GstRTSPMediaFactory *factory, + gboolean shared); +gboolean gst_rtsp_media_factory_is_shared (GstRTSPMediaFactory *factory); + +void gst_rtsp_media_factory_set_suspend_mode (GstRTSPMediaFactory *factory, + GstRTSPSuspendMode mode); +GstRTSPSuspendMode gst_rtsp_media_factory_get_suspend_mode (GstRTSPMediaFactory *factory); + +void gst_rtsp_media_factory_set_eos_shutdown (GstRTSPMediaFactory *factory, + gboolean eos_shutdown); +gboolean gst_rtsp_media_factory_is_eos_shutdown (GstRTSPMediaFactory *factory); + +void gst_rtsp_media_factory_set_profiles (GstRTSPMediaFactory *factory, + GstRTSPProfile profiles); +GstRTSPProfile gst_rtsp_media_factory_get_profiles (GstRTSPMediaFactory *factory); + +void gst_rtsp_media_factory_set_protocols (GstRTSPMediaFactory *factory, + GstRTSPLowerTrans protocols); +GstRTSPLowerTrans gst_rtsp_media_factory_get_protocols (GstRTSPMediaFactory *factory); + +void gst_rtsp_media_factory_set_address_pool (GstRTSPMediaFactory * factory, + GstRTSPAddressPool * pool); +GstRTSPAddressPool * gst_rtsp_media_factory_get_address_pool (GstRTSPMediaFactory * factory); + +void gst_rtsp_media_factory_set_buffer_size (GstRTSPMediaFactory * factory, + guint size); +guint gst_rtsp_media_factory_get_buffer_size (GstRTSPMediaFactory * factory); + +/* creating the media from the factory and a url */ +GstRTSPMedia * gst_rtsp_media_factory_construct (GstRTSPMediaFactory *factory, + const GstRTSPUrl *url); + +GstElement * gst_rtsp_media_factory_create_element (GstRTSPMediaFactory *factory, + const GstRTSPUrl *url); + +G_END_DECLS + +#endif /* __GST_RTSP_MEDIA_FACTORY_H__ */ diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c new file mode 100644 index 0000000..6b81e25 --- /dev/null +++ b/gst/rtsp-server/rtsp-media.c @@ -0,0 +1,3092 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-media + * @short_description: The media pipeline + * @see_also: #GstRTSPMediaFactory, #GstRTSPStream, #GstRTSPSession, + * #GstRTSPSessionMedia + * + * a #GstRTSPMedia contains the complete GStreamer pipeline to manage the + * streaming to the clients. The actual data transfer is done by the + * #GstRTSPStream objects that are created and exposed by the #GstRTSPMedia. + * + * The #GstRTSPMedia is usually created from a #GstRTSPMediaFactory when the + * client does a DESCRIBE or SETUP of a resource. + * + * A media is created with gst_rtsp_media_new() that takes the element that will + * provide the streaming elements. For each of the streams, a new #GstRTSPStream + * object needs to be made with the gst_rtsp_media_create_stream() which takes + * the payloader element and the source pad that produces the RTP stream. + * + * The pipeline of the media is set to PAUSED with gst_rtsp_media_prepare(). The + * prepare method will add rtpbin and sinks and sources to send and receive RTP + * and RTCP packets from the clients. Each stream srcpad is connected to an + * input into the internal rtpbin. + * + * It is also possible to dynamically create #GstRTSPStream objects during the + * prepare phase. With gst_rtsp_media_get_status() you can check the status of + * the prepare phase. + * + * After the media is prepared, it is ready for streaming. It will usually be + * managed in a session with gst_rtsp_session_manage_media(). See + * #GstRTSPSession and #GstRTSPSessionMedia. + * + * The state of the media can be controlled with gst_rtsp_media_set_state (). + * Seeking can be done with gst_rtsp_media_seek(). + * + * With gst_rtsp_media_unprepare() the pipeline is stopped and shut down. When + * gst_rtsp_media_set_eos_shutdown() an EOS will be sent to the pipeline to + * cleanly shut down. + * + * With gst_rtsp_media_set_shared(), the media can be shared between multiple + * clients. With gst_rtsp_media_set_reusable() you can control if the pipeline + * can be prepared again after an unprepare. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include +#include + +#include +#include + +#include "rtsp-media.h" + +#define GST_RTSP_MEDIA_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA, GstRTSPMediaPrivate)) + +struct _GstRTSPMediaPrivate +{ + GMutex lock; + GCond cond; + + /* protected by lock */ + GstRTSPPermissions *permissions; + gboolean shared; + gboolean suspend_mode; + gboolean reusable; + GstRTSPProfile profiles; + GstRTSPLowerTrans protocols; + gboolean reused; + gboolean eos_shutdown; + guint buffer_size; + GstRTSPAddressPool *pool; + gboolean blocked; + + GstElement *element; + GRecMutex state_lock; /* locking order: state lock, lock */ + GPtrArray *streams; /* protected by lock */ + GList *dynamic; /* protected by lock */ + GstRTSPMediaStatus status; /* protected by lock */ + gint prepare_count; + gint n_active; + gboolean adding; + + /* the pipeline for the media */ + GstElement *pipeline; + GstElement *fakesink; /* protected by lock */ + GSource *source; + guint id; + GstRTSPThread *thread; + + gboolean time_provider; + GstNetTimeProvider *nettime; + + gboolean is_live; + gboolean seekable; + gboolean buffering; + GstState target_state; + + /* RTP session manager */ + GstElement *rtpbin; + + /* the range of media */ + GstRTSPTimeRange range; /* protected by lock */ + GstClockTime range_start; + GstClockTime range_stop; +}; + +#define DEFAULT_SHARED FALSE +#define DEFAULT_SUSPEND_MODE GST_RTSP_SUSPEND_MODE_NONE +#define DEFAULT_REUSABLE FALSE +#define DEFAULT_PROFILES GST_RTSP_PROFILE_AVP +#define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \ + GST_RTSP_LOWER_TRANS_TCP +#define DEFAULT_EOS_SHUTDOWN FALSE +#define DEFAULT_BUFFER_SIZE 0x80000 +#define DEFAULT_TIME_PROVIDER FALSE + +/* define to dump received RTCP packets */ +#undef DUMP_STATS + +enum +{ + PROP_0, + PROP_SHARED, + PROP_SUSPEND_MODE, + PROP_REUSABLE, + PROP_PROFILES, + PROP_PROTOCOLS, + PROP_EOS_SHUTDOWN, + PROP_BUFFER_SIZE, + PROP_ELEMENT, + PROP_TIME_PROVIDER, + PROP_LAST +}; + +enum +{ + SIGNAL_NEW_STREAM, + SIGNAL_REMOVED_STREAM, + SIGNAL_PREPARED, + SIGNAL_UNPREPARED, + SIGNAL_TARGET_STATE, + SIGNAL_NEW_STATE, + SIGNAL_LAST +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug); +#define GST_CAT_DEFAULT rtsp_media_debug + +static void gst_rtsp_media_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_media_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); +static void gst_rtsp_media_finalize (GObject * obj); + +static gboolean default_handle_message (GstRTSPMedia * media, + GstMessage * message); +static void finish_unprepare (GstRTSPMedia * media); +static gboolean default_prepare (GstRTSPMedia * media, GstRTSPThread * thread); +static gboolean default_unprepare (GstRTSPMedia * media); +static gboolean default_suspend (GstRTSPMedia * media); +static gboolean default_unsuspend (GstRTSPMedia * media); +static gboolean default_convert_range (GstRTSPMedia * media, + GstRTSPTimeRange * range, GstRTSPRangeUnit unit); +static gboolean default_query_position (GstRTSPMedia * media, + gint64 * position); +static gboolean default_query_stop (GstRTSPMedia * media, gint64 * stop); +static GstElement *default_create_rtpbin (GstRTSPMedia * media); +static gboolean default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, + GstSDPInfo * info); + +static gboolean wait_preroll (GstRTSPMedia * media); + +static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 }; + +#define C_ENUM(v) ((gint) v) + +#define GST_TYPE_RTSP_SUSPEND_MODE (gst_rtsp_suspend_mode_get_type()) +GType +gst_rtsp_suspend_mode_get_type (void) +{ + static gsize id = 0; + static const GEnumValue values[] = { + {C_ENUM (GST_RTSP_SUSPEND_MODE_NONE), "GST_RTSP_SUSPEND_MODE_NONE", "none"}, + {C_ENUM (GST_RTSP_SUSPEND_MODE_PAUSE), "GST_RTSP_SUSPEND_MODE_PAUSE", + "pause"}, + {C_ENUM (GST_RTSP_SUSPEND_MODE_RESET), "GST_RTSP_SUSPEND_MODE_RESET", + "reset"}, + {0, NULL, NULL} + }; + + if (g_once_init_enter (&id)) { + GType tmp = g_enum_register_static ("GstRTSPSuspendMode", values); + g_once_init_leave (&id, tmp); + } + return (GType) id; +} + +G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT); + +static void +gst_rtsp_media_class_init (GstRTSPMediaClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPMediaPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gst_rtsp_media_get_property; + gobject_class->set_property = gst_rtsp_media_set_property; + gobject_class->finalize = gst_rtsp_media_finalize; + + g_object_class_install_property (gobject_class, PROP_SHARED, + g_param_spec_boolean ("shared", "Shared", + "If this media pipeline can be shared", DEFAULT_SHARED, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_SUSPEND_MODE, + g_param_spec_enum ("suspend-mode", "Suspend Mode", + "How to suspend the media in PAUSED", GST_TYPE_RTSP_SUSPEND_MODE, + DEFAULT_SUSPEND_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_REUSABLE, + g_param_spec_boolean ("reusable", "Reusable", + "If this media pipeline can be reused after an unprepare", + DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_PROFILES, + g_param_spec_flags ("profiles", "Profiles", + "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE, + DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_PROTOCOLS, + g_param_spec_flags ("protocols", "Protocols", + "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS, + DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN, + g_param_spec_boolean ("eos-shutdown", "EOS Shutdown", + "Send an EOS event to the pipeline before unpreparing", + DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE, + g_param_spec_uint ("buffer-size", "Buffer Size", + "The kernel UDP buffer size to use", 0, G_MAXUINT, + DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_ELEMENT, + g_param_spec_object ("element", "The Element", + "The GstBin to use for streaming the media", GST_TYPE_ELEMENT, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_TIME_PROVIDER, + g_param_spec_boolean ("time-provider", "Time Provider", + "Use a NetTimeProvider for clients", + DEFAULT_TIME_PROVIDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_rtsp_media_signals[SIGNAL_NEW_STREAM] = + g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM); + + gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM] = + g_signal_new ("removed-stream", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, removed_stream), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_RTSP_STREAM); + + gst_rtsp_media_signals[SIGNAL_PREPARED] = + g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE); + + gst_rtsp_media_signals[SIGNAL_UNPREPARED] = + g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE); + + gst_rtsp_media_signals[SIGNAL_TARGET_STATE] = + g_signal_new ("target-state", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, target_state), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_INT); + + gst_rtsp_media_signals[SIGNAL_NEW_STATE] = + g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_INT); + + GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia"); + + klass->handle_message = default_handle_message; + klass->prepare = default_prepare; + klass->unprepare = default_unprepare; + klass->suspend = default_suspend; + klass->unsuspend = default_unsuspend; + klass->convert_range = default_convert_range; + klass->query_position = default_query_position; + klass->query_stop = default_query_stop; + klass->create_rtpbin = default_create_rtpbin; + klass->setup_sdp = default_setup_sdp; +} + +static void +gst_rtsp_media_init (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = GST_RTSP_MEDIA_GET_PRIVATE (media); + + media->priv = priv; + + priv->streams = g_ptr_array_new_with_free_func (g_object_unref); + g_mutex_init (&priv->lock); + g_cond_init (&priv->cond); + g_rec_mutex_init (&priv->state_lock); + + priv->shared = DEFAULT_SHARED; + priv->suspend_mode = DEFAULT_SUSPEND_MODE; + priv->reusable = DEFAULT_REUSABLE; + priv->profiles = DEFAULT_PROFILES; + priv->protocols = DEFAULT_PROTOCOLS; + priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN; + priv->buffer_size = DEFAULT_BUFFER_SIZE; + priv->time_provider = DEFAULT_TIME_PROVIDER; +} + +static void +gst_rtsp_media_finalize (GObject * obj) +{ + GstRTSPMediaPrivate *priv; + GstRTSPMedia *media; + + media = GST_RTSP_MEDIA (obj); + priv = media->priv; + + GST_INFO ("finalize media %p", media); + + if (priv->permissions) + gst_rtsp_permissions_unref (priv->permissions); + + g_ptr_array_unref (priv->streams); + + g_list_free_full (priv->dynamic, gst_object_unref); + + if (priv->pipeline) + gst_object_unref (priv->pipeline); + if (priv->nettime) + gst_object_unref (priv->nettime); + gst_object_unref (priv->element); + if (priv->pool) + g_object_unref (priv->pool); + g_mutex_clear (&priv->lock); + g_cond_clear (&priv->cond); + g_rec_mutex_clear (&priv->state_lock); + + G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj); +} + +static void +gst_rtsp_media_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + GstRTSPMedia *media = GST_RTSP_MEDIA (object); + + switch (propid) { + case PROP_ELEMENT: + g_value_set_object (value, media->priv->element); + break; + case PROP_SHARED: + g_value_set_boolean (value, gst_rtsp_media_is_shared (media)); + break; + case PROP_SUSPEND_MODE: + g_value_set_enum (value, gst_rtsp_media_get_suspend_mode (media)); + break; + case PROP_REUSABLE: + g_value_set_boolean (value, gst_rtsp_media_is_reusable (media)); + break; + case PROP_PROFILES: + g_value_set_flags (value, gst_rtsp_media_get_profiles (media)); + break; + case PROP_PROTOCOLS: + g_value_set_flags (value, gst_rtsp_media_get_protocols (media)); + break; + case PROP_EOS_SHUTDOWN: + g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media)); + break; + case PROP_BUFFER_SIZE: + g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media)); + break; + case PROP_TIME_PROVIDER: + g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_media_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + GstRTSPMedia *media = GST_RTSP_MEDIA (object); + + switch (propid) { + case PROP_ELEMENT: + media->priv->element = g_value_get_object (value); + gst_object_ref_sink (media->priv->element); + break; + case PROP_SHARED: + gst_rtsp_media_set_shared (media, g_value_get_boolean (value)); + break; + case PROP_SUSPEND_MODE: + gst_rtsp_media_set_suspend_mode (media, g_value_get_enum (value)); + break; + case PROP_REUSABLE: + gst_rtsp_media_set_reusable (media, g_value_get_boolean (value)); + break; + case PROP_PROFILES: + gst_rtsp_media_set_profiles (media, g_value_get_flags (value)); + break; + case PROP_PROTOCOLS: + gst_rtsp_media_set_protocols (media, g_value_get_flags (value)); + break; + case PROP_EOS_SHUTDOWN: + gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value)); + break; + case PROP_BUFFER_SIZE: + gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value)); + break; + case PROP_TIME_PROVIDER: + gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +typedef struct +{ + gint64 position; + gboolean ret; +} DoQueryPositionData; + +static void +do_query_position (GstRTSPStream * stream, DoQueryPositionData * data) +{ + gint64 tmp; + + if (gst_rtsp_stream_query_position (stream, &tmp)) { + data->position = MAX (data->position, tmp); + data->ret = TRUE; + } +} + +static gboolean +default_query_position (GstRTSPMedia * media, gint64 * position) +{ + GstRTSPMediaPrivate *priv; + DoQueryPositionData data; + + priv = media->priv; + + data.position = -1; + data.ret = FALSE; + + g_ptr_array_foreach (priv->streams, (GFunc) do_query_position, &data); + + *position = data.position; + + return data.ret; +} + +typedef struct +{ + gint64 stop; + gboolean ret; +} DoQueryStopData; + +static void +do_query_stop (GstRTSPStream * stream, DoQueryStopData * data) +{ + gint64 tmp; + + if (gst_rtsp_stream_query_stop (stream, &tmp)) { + data->stop = MAX (data->stop, tmp); + data->ret = TRUE; + } +} + +static gboolean +default_query_stop (GstRTSPMedia * media, gint64 * stop) +{ + GstRTSPMediaPrivate *priv; + DoQueryStopData data; + + priv = media->priv; + + data.stop = -1; + data.ret = FALSE; + + g_ptr_array_foreach (priv->streams, (GFunc) do_query_stop, &data); + + *stop = data.stop; + + return data.ret; +} + +static GstElement * +default_create_rtpbin (GstRTSPMedia * media) +{ + GstElement *rtpbin; + + rtpbin = gst_element_factory_make ("rtpbin", NULL); + + return rtpbin; +} + +/* must be called with state lock */ +static void +collect_media_stats (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + gint64 position = 0, stop = -1; + + if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED && + priv->status != GST_RTSP_MEDIA_STATUS_PREPARING) + return; + + priv->range.unit = GST_RTSP_RANGE_NPT; + + GST_INFO ("collect media stats"); + + if (priv->is_live) { + priv->range.min.type = GST_RTSP_TIME_NOW; + priv->range.min.seconds = -1; + priv->range_start = -1; + priv->range.max.type = GST_RTSP_TIME_END; + priv->range.max.seconds = -1; + priv->range_stop = -1; + } else { + GstRTSPMediaClass *klass; + gboolean ret; + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + + /* get the position */ + ret = FALSE; + if (klass->query_position) + ret = klass->query_position (media, &position); + + if (!ret) { + GST_INFO ("position query failed"); + position = 0; + } + + /* get the current segment stop */ + ret = FALSE; + if (klass->query_stop) + ret = klass->query_stop (media, &stop); + + if (!ret) { + GST_INFO ("stop query failed"); + stop = -1; + } + + GST_INFO ("stats: position %" GST_TIME_FORMAT ", stop %" + GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (stop)); + + if (position == -1) { + priv->range.min.type = GST_RTSP_TIME_NOW; + priv->range.min.seconds = -1; + priv->range_start = -1; + } else { + priv->range.min.type = GST_RTSP_TIME_SECONDS; + priv->range.min.seconds = ((gdouble) position) / GST_SECOND; + priv->range_start = position; + } + if (stop == -1) { + priv->range.max.type = GST_RTSP_TIME_END; + priv->range.max.seconds = -1; + priv->range_stop = -1; + } else { + priv->range.max.type = GST_RTSP_TIME_SECONDS; + priv->range.max.seconds = ((gdouble) stop) / GST_SECOND; + priv->range_stop = stop; + } + } +} + +/** + * gst_rtsp_media_new: + * @element: (transfer full): a #GstElement + * + * Create a new #GstRTSPMedia instance. @element is the bin element that + * provides the different streams. The #GstRTSPMedia object contains the + * element to produce RTP data for one or more related (audio/video/..) + * streams. + * + * Ownership is taken of @element. + * + * Returns: (transfer full): a new #GstRTSPMedia object. + */ +GstRTSPMedia * +gst_rtsp_media_new (GstElement * element) +{ + GstRTSPMedia *result; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + result = g_object_new (GST_TYPE_RTSP_MEDIA, "element", element, NULL); + + return result; +} + +/** + * gst_rtsp_media_get_element: + * @media: a #GstRTSPMedia + * + * Get the element that was used when constructing @media. + * + * Returns: (transfer full): a #GstElement. Unref after usage. + */ +GstElement * +gst_rtsp_media_get_element (GstRTSPMedia * media) +{ + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); + + return gst_object_ref (media->priv->element); +} + +/** + * gst_rtsp_media_take_pipeline: + * @media: a #GstRTSPMedia + * @pipeline: (transfer full): a #GstPipeline + * + * Set @pipeline as the #GstPipeline for @media. Ownership is + * taken of @pipeline. + */ +void +gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline) +{ + GstRTSPMediaPrivate *priv; + GstElement *old; + GstNetTimeProvider *nettime; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + g_return_if_fail (GST_IS_PIPELINE (pipeline)); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + old = priv->pipeline; + priv->pipeline = GST_ELEMENT_CAST (pipeline); + nettime = priv->nettime; + priv->nettime = NULL; + g_mutex_unlock (&priv->lock); + + if (old) + gst_object_unref (old); + + if (nettime) + gst_object_unref (nettime); + + gst_bin_add (GST_BIN_CAST (pipeline), priv->element); +} + +/** + * gst_rtsp_media_set_permissions: + * @media: a #GstRTSPMedia + * @permissions: (transfer none): a #GstRTSPPermissions + * + * Set @permissions on @media. + */ +void +gst_rtsp_media_set_permissions (GstRTSPMedia * media, + GstRTSPPermissions * permissions) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + if (priv->permissions) + gst_rtsp_permissions_unref (priv->permissions); + if ((priv->permissions = permissions)) + gst_rtsp_permissions_ref (permissions); + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_media_get_permissions: + * @media: a #GstRTSPMedia + * + * Get the permissions object from @media. + * + * Returns: (transfer full): a #GstRTSPPermissions object, unref after usage. + */ +GstRTSPPermissions * +gst_rtsp_media_get_permissions (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + GstRTSPPermissions *result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + if ((result = priv->permissions)) + gst_rtsp_permissions_ref (result); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_media_set_suspend_mode: + * @media: a #GstRTSPMedia + * @mode: the new #GstRTSPSuspendMode + * + * Control how @ media will be suspended after the SDP has been generated and + * after a PAUSE request has been performed. + * + * Media must be unprepared when setting the suspend mode. + */ +void +gst_rtsp_media_set_suspend_mode (GstRTSPMedia * media, GstRTSPSuspendMode mode) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + priv = media->priv; + + g_rec_mutex_lock (&priv->state_lock); + if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) + goto was_prepared; + priv->suspend_mode = mode; + g_rec_mutex_unlock (&priv->state_lock); + + return; + + /* ERRORS */ +was_prepared: + { + GST_WARNING ("media %p was prepared", media); + g_rec_mutex_unlock (&priv->state_lock); + } +} + +/** + * gst_rtsp_media_get_suspend_mode: + * @media: a #GstRTSPMedia + * + * Get how @media will be suspended. + * + * Returns: #GstRTSPSuspendMode. + */ +GstRTSPSuspendMode +gst_rtsp_media_get_suspend_mode (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + GstRTSPSuspendMode res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_SUSPEND_MODE_NONE); + + priv = media->priv; + + g_rec_mutex_lock (&priv->state_lock); + res = priv->suspend_mode; + g_rec_mutex_unlock (&priv->state_lock); + + return res; +} + +/** + * gst_rtsp_media_set_shared: + * @media: a #GstRTSPMedia + * @shared: the new value + * + * Set or unset if the pipeline for @media can be shared will multiple clients. + * When @shared is %TRUE, client requests for this media will share the media + * pipeline. + */ +void +gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + priv->shared = shared; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_media_is_shared: + * @media: a #GstRTSPMedia + * + * Check if the pipeline for @media can be shared between multiple clients. + * + * Returns: %TRUE if the media can be shared between clients. + */ +gboolean +gst_rtsp_media_is_shared (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + gboolean res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + res = priv->shared; + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_media_set_reusable: + * @media: a #GstRTSPMedia + * @reusable: the new value + * + * Set or unset if the pipeline for @media can be reused after the pipeline has + * been unprepared. + */ +void +gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + priv->reusable = reusable; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_media_is_reusable: + * @media: a #GstRTSPMedia + * + * Check if the pipeline for @media can be reused after an unprepare. + * + * Returns: %TRUE if the media can be reused + */ +gboolean +gst_rtsp_media_is_reusable (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + gboolean res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + res = priv->reusable; + g_mutex_unlock (&priv->lock); + + return res; +} + +static void +do_set_profiles (GstRTSPStream * stream, GstRTSPProfile * profiles) +{ + gst_rtsp_stream_set_profiles (stream, *profiles); +} + +/** + * gst_rtsp_media_set_profiles: + * @media: a #GstRTSPMedia + * @profiles: the new flags + * + * Configure the allowed lower transport for @media. + */ +void +gst_rtsp_media_set_profiles (GstRTSPMedia * media, GstRTSPProfile profiles) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + priv->profiles = profiles; + g_ptr_array_foreach (priv->streams, (GFunc) do_set_profiles, &profiles); + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_media_get_profiles: + * @media: a #GstRTSPMedia + * + * Get the allowed profiles of @media. + * + * Returns: a #GstRTSPProfile + */ +GstRTSPProfile +gst_rtsp_media_get_profiles (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + GstRTSPProfile res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_RTSP_PROFILE_UNKNOWN); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + res = priv->profiles; + g_mutex_unlock (&priv->lock); + + return res; +} + +static void +do_set_protocols (GstRTSPStream * stream, GstRTSPLowerTrans * protocols) +{ + gst_rtsp_stream_set_protocols (stream, *protocols); +} + +/** + * gst_rtsp_media_set_protocols: + * @media: a #GstRTSPMedia + * @protocols: the new flags + * + * Configure the allowed lower transport for @media. + */ +void +gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + priv->protocols = protocols; + g_ptr_array_foreach (priv->streams, (GFunc) do_set_protocols, &protocols); + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_media_get_protocols: + * @media: a #GstRTSPMedia + * + * Get the allowed protocols of @media. + * + * Returns: a #GstRTSPLowerTrans + */ +GstRTSPLowerTrans +gst_rtsp_media_get_protocols (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + GstRTSPLowerTrans res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), + GST_RTSP_LOWER_TRANS_UNKNOWN); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + res = priv->protocols; + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_media_set_eos_shutdown: + * @media: a #GstRTSPMedia + * @eos_shutdown: the new value + * + * Set or unset if an EOS event will be sent to the pipeline for @media before + * it is unprepared. + */ +void +gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + priv->eos_shutdown = eos_shutdown; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_media_is_eos_shutdown: + * @media: a #GstRTSPMedia + * + * Check if the pipeline for @media will send an EOS down the pipeline before + * unpreparing. + * + * Returns: %TRUE if the media will send EOS before unpreparing. + */ +gboolean +gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + gboolean res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + res = priv->eos_shutdown; + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_media_set_buffer_size: + * @media: a #GstRTSPMedia + * @size: the new value + * + * Set the kernel UDP buffer size. + */ +void +gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + GST_LOG_OBJECT (media, "set buffer size %u", size); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + priv->buffer_size = size; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_media_get_buffer_size: + * @media: a #GstRTSPMedia + * + * Get the kernel UDP buffer size. + * + * Returns: the kernel UDP buffer size. + */ +guint +gst_rtsp_media_get_buffer_size (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + guint res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + + priv = media->priv; + + g_mutex_unlock (&priv->lock); + res = priv->buffer_size; + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_media_use_time_provider: + * @media: a #GstRTSPMedia + * @time_provider: if a #GstNetTimeProvider should be used + * + * Set @media to provide a #GstNetTimeProvider. + */ +void +gst_rtsp_media_use_time_provider (GstRTSPMedia * media, gboolean time_provider) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + priv->time_provider = time_provider; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_media_is_time_provider: + * @media: a #GstRTSPMedia + * + * Check if @media can provide a #GstNetTimeProvider for its pipeline clock. + * + * Use gst_rtsp_media_get_time_provider() to get the network clock. + * + * Returns: %TRUE if @media can provide a #GstNetTimeProvider. + */ +gboolean +gst_rtsp_media_is_time_provider (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + gboolean res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + + priv = media->priv; + + g_mutex_unlock (&priv->lock); + res = priv->time_provider; + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_media_set_address_pool: + * @media: a #GstRTSPMedia + * @pool: (transfer none): a #GstRTSPAddressPool + * + * configure @pool to be used as the address pool of @media. + */ +void +gst_rtsp_media_set_address_pool (GstRTSPMedia * media, + GstRTSPAddressPool * pool) +{ + GstRTSPMediaPrivate *priv; + GstRTSPAddressPool *old; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + priv = media->priv; + + GST_LOG_OBJECT (media, "set address pool %p", pool); + + g_mutex_lock (&priv->lock); + if ((old = priv->pool) != pool) + priv->pool = pool ? g_object_ref (pool) : NULL; + else + old = NULL; + g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool, + pool); + g_mutex_unlock (&priv->lock); + + if (old) + g_object_unref (old); +} + +/** + * gst_rtsp_media_get_address_pool: + * @media: a #GstRTSPMedia + * + * Get the #GstRTSPAddressPool used as the address pool of @media. + * + * Returns: (transfer full): the #GstRTSPAddressPool of @media. g_object_unref() after + * usage. + */ +GstRTSPAddressPool * +gst_rtsp_media_get_address_pool (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + GstRTSPAddressPool *result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + if ((result = priv->pool)) + g_object_ref (result); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_media_collect_streams: + * @media: a #GstRTSPMedia + * + * Find all payloader elements, they should be named pay\%d in the + * element of @media, and create #GstRTSPStreams for them. + * + * Collect all dynamic elements, named dynpay\%d, and add them to + * the list of dynamic elements. + */ +void +gst_rtsp_media_collect_streams (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + GstElement *element, *elem; + GstPad *pad; + gint i; + gboolean have_elem; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + priv = media->priv; + element = priv->element; + + have_elem = TRUE; + for (i = 0; have_elem; i++) { + gchar *name; + + have_elem = FALSE; + + name = g_strdup_printf ("pay%d", i); + if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) { + GST_INFO ("found stream %d with payloader %p", i, elem); + + /* take the pad of the payloader */ + pad = gst_element_get_static_pad (elem, "src"); + /* create the stream */ + gst_rtsp_media_create_stream (media, elem, pad); + gst_object_unref (pad); + gst_object_unref (elem); + + have_elem = TRUE; + } + g_free (name); + + name = g_strdup_printf ("dynpay%d", i); + if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) { + /* a stream that will dynamically create pads to provide RTP packets */ + GST_INFO ("found dynamic element %d, %p", i, elem); + + g_mutex_lock (&priv->lock); + priv->dynamic = g_list_prepend (priv->dynamic, elem); + g_mutex_unlock (&priv->lock); + + have_elem = TRUE; + } + g_free (name); + } +} + +/** + * gst_rtsp_media_create_stream: + * @media: a #GstRTSPMedia + * @payloader: a #GstElement + * @srcpad: a source #GstPad + * + * Create a new stream in @media that provides RTP data on @srcpad. + * @srcpad should be a pad of an element inside @media->element. + * + * Returns: (transfer none): a new #GstRTSPStream that remains valid for as long + * as @media exists. + */ +GstRTSPStream * +gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader, + GstPad * pad) +{ + GstRTSPMediaPrivate *priv; + GstRTSPStream *stream; + GstPad *srcpad; + gchar *name; + gint idx; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); + g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL); + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + idx = priv->streams->len; + + GST_DEBUG ("media %p: creating stream with index %d", media, idx); + + name = g_strdup_printf ("src_%u", idx); + srcpad = gst_ghost_pad_new (name, pad); + gst_pad_set_active (srcpad, TRUE); + gst_element_add_pad (priv->element, srcpad); + g_free (name); + + stream = gst_rtsp_stream_new (idx, payloader, srcpad); + if (priv->pool) + gst_rtsp_stream_set_address_pool (stream, priv->pool); + gst_rtsp_stream_set_profiles (stream, priv->profiles); + gst_rtsp_stream_set_protocols (stream, priv->protocols); + + g_ptr_array_add (priv->streams, stream); + g_mutex_unlock (&priv->lock); + + g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream, + NULL); + + return stream; +} + +static void +gst_rtsp_media_remove_stream (GstRTSPMedia * media, GstRTSPStream * stream) +{ + GstRTSPMediaPrivate *priv; + GstPad *srcpad; + + priv = media->priv; + + g_mutex_lock (&priv->lock); + /* remove the ghostpad */ + srcpad = gst_rtsp_stream_get_srcpad (stream); + gst_element_remove_pad (priv->element, srcpad); + gst_object_unref (srcpad); + /* now remove the stream */ + g_object_ref (stream); + g_ptr_array_remove (priv->streams, stream); + g_mutex_unlock (&priv->lock); + + g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM], 0, + stream, NULL); + + g_object_unref (stream); +} + +/** + * gst_rtsp_media_n_streams: + * @media: a #GstRTSPMedia + * + * Get the number of streams in this media. + * + * Returns: The number of streams. + */ +guint +gst_rtsp_media_n_streams (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + guint res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + res = priv->streams->len; + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_media_get_stream: + * @media: a #GstRTSPMedia + * @idx: the stream index + * + * Retrieve the stream with index @idx from @media. + * + * Returns: (nullable) (transfer none): the #GstRTSPStream at index + * @idx or %NULL when a stream with that index did not exist. + */ +GstRTSPStream * +gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx) +{ + GstRTSPMediaPrivate *priv; + GstRTSPStream *res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + if (idx < priv->streams->len) + res = g_ptr_array_index (priv->streams, idx); + else + res = NULL; + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_media_find_stream: + * @media: a #GstRTSPMedia + * @control: the control of the stream + * + * Find a stream in @media with @control as the control uri. + * + * Returns: (nullable) (transfer none): the #GstRTSPStream with + * control uri @control or %NULL when a stream with that control did + * not exist. + */ +GstRTSPStream * +gst_rtsp_media_find_stream (GstRTSPMedia * media, const gchar * control) +{ + GstRTSPMediaPrivate *priv; + GstRTSPStream *res; + gint i; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); + g_return_val_if_fail (control != NULL, NULL); + + priv = media->priv; + + res = NULL; + + g_mutex_lock (&priv->lock); + for (i = 0; i < priv->streams->len; i++) { + GstRTSPStream *test; + + test = g_ptr_array_index (priv->streams, i); + if (gst_rtsp_stream_has_control (test, control)) { + res = test; + break; + } + } + g_mutex_unlock (&priv->lock); + + return res; +} + +/* called with state-lock */ +static gboolean +default_convert_range (GstRTSPMedia * media, GstRTSPTimeRange * range, + GstRTSPRangeUnit unit) +{ + return gst_rtsp_range_convert_units (range, unit); +} + +/** + * gst_rtsp_media_get_range_string: + * @media: a #GstRTSPMedia + * @play: for the PLAY request + * @unit: the unit to use for the string + * + * Get the current range as a string. @media must be prepared with + * gst_rtsp_media_prepare (). + * + * Returns: (transfer full): The range as a string, g_free() after usage. + */ +gchar * +gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play, + GstRTSPRangeUnit unit) +{ + GstRTSPMediaClass *klass; + GstRTSPMediaPrivate *priv; + gchar *result; + GstRTSPTimeRange range; + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); + g_return_val_if_fail (klass->convert_range != NULL, FALSE); + + priv = media->priv; + + g_rec_mutex_lock (&priv->state_lock); + if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED && + priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED) + goto not_prepared; + + g_mutex_lock (&priv->lock); + + /* Update the range value with current position/duration */ + collect_media_stats (media); + + /* make copy */ + range = priv->range; + + if (!play && priv->n_active > 0) { + range.min.type = GST_RTSP_TIME_NOW; + range.min.seconds = -1; + } + g_mutex_unlock (&priv->lock); + g_rec_mutex_unlock (&priv->state_lock); + + if (!klass->convert_range (media, &range, unit)) + goto conversion_failed; + + result = gst_rtsp_range_to_string (&range); + + return result; + + /* ERRORS */ +not_prepared: + { + GST_WARNING ("media %p was not prepared", media); + g_rec_mutex_unlock (&priv->state_lock); + return NULL; + } +conversion_failed: + { + GST_WARNING ("range conversion to unit %d failed", unit); + return NULL; + } +} + +static void +stream_update_blocked (GstRTSPStream * stream, GstRTSPMedia * media) +{ + gst_rtsp_stream_set_blocked (stream, media->priv->blocked); +} + +static void +media_streams_set_blocked (GstRTSPMedia * media, gboolean blocked) +{ + GstRTSPMediaPrivate *priv = media->priv; + + GST_DEBUG ("media %p set blocked %d", media, blocked); + priv->blocked = blocked; + g_ptr_array_foreach (priv->streams, (GFunc) stream_update_blocked, media); +} + +static void +gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status) +{ + GstRTSPMediaPrivate *priv = media->priv; + + g_mutex_lock (&priv->lock); + priv->status = status; + GST_DEBUG ("setting new status to %d", status); + g_cond_broadcast (&priv->cond); + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_media_get_status: + * @media: a #GstRTSPMedia + * + * Get the status of @media. When @media is busy preparing, this function waits + * until @media is prepared or in error. + * + * Returns: the status of @media. + */ +GstRTSPMediaStatus +gst_rtsp_media_get_status (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstRTSPMediaStatus result; + gint64 end_time; + + g_mutex_lock (&priv->lock); + end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND; + /* while we are preparing, wait */ + while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) { + GST_DEBUG ("waiting for status change"); + if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) { + GST_DEBUG ("timeout, assuming error status"); + priv->status = GST_RTSP_MEDIA_STATUS_ERROR; + } + } + /* could be success or error */ + result = priv->status; + GST_DEBUG ("got status %d", result); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_media_seek: + * @media: a #GstRTSPMedia + * @range: (transfer none): a #GstRTSPTimeRange + * + * Seek the pipeline of @media to @range. @media must be prepared with + * gst_rtsp_media_prepare(). + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range) +{ + GstRTSPMediaClass *klass; + GstRTSPMediaPrivate *priv; + gboolean res; + GstClockTime start, stop; + GstSeekType start_type, stop_type; + GstQuery *query; + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + g_return_val_if_fail (range != NULL, FALSE); + g_return_val_if_fail (klass->convert_range != NULL, FALSE); + + priv = media->priv; + + g_rec_mutex_lock (&priv->state_lock); + if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) + goto not_prepared; + + /* Update the seekable state of the pipeline in case it changed */ + query = gst_query_new_seeking (GST_FORMAT_TIME); + if (gst_element_query (priv->pipeline, query)) { + GstFormat format; + gboolean seekable; + gint64 start, end; + + gst_query_parse_seeking (query, &format, &seekable, &start, &end); + priv->seekable = seekable; + } + gst_query_unref (query); + + if (!priv->seekable) + goto not_seekable; + + start_type = stop_type = GST_SEEK_TYPE_NONE; + + if (!klass->convert_range (media, range, GST_RTSP_RANGE_NPT)) + goto not_supported; + gst_rtsp_range_get_times (range, &start, &stop); + + GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT, + GST_TIME_ARGS (start), GST_TIME_ARGS (stop)); + GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT, + GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop)); + + if (start != GST_CLOCK_TIME_NONE) + start_type = GST_SEEK_TYPE_SET; + + if (priv->range_stop == stop) + stop = GST_CLOCK_TIME_NONE; + else if (stop != GST_CLOCK_TIME_NONE) + stop_type = GST_SEEK_TYPE_SET; + + if (start != GST_CLOCK_TIME_NONE || stop != GST_CLOCK_TIME_NONE) { + GstSeekFlags flags; + + GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT, + GST_TIME_ARGS (start), GST_TIME_ARGS (stop)); + + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING); + if (priv->blocked) + media_streams_set_blocked (media, TRUE); + + /* depends on the current playing state of the pipeline. We might need to + * queue this until we get EOS. */ + flags = GST_SEEK_FLAG_FLUSH; + + /* if range start was not supplied we must continue from current position. + * but since we're doing a flushing seek, let us query the current position + * so we end up at exactly the same position after the seek. */ + if (range->min.type == GST_RTSP_TIME_END) { /* Yepp, that's right! */ + gint64 position; + gboolean ret = FALSE; + + if (klass->query_position) + ret = klass->query_position (media, &position); + + if (!ret) { + GST_WARNING ("position query failed"); + } else { + GST_DEBUG ("doing accurate seek to %" GST_TIME_FORMAT, + GST_TIME_ARGS (position)); + start = position; + start_type = GST_SEEK_TYPE_SET; + flags |= GST_SEEK_FLAG_ACCURATE; + } + } else { + /* only set keyframe flag when modifying start */ + if (start_type != GST_SEEK_TYPE_NONE) + flags |= GST_SEEK_FLAG_KEY_UNIT; + } + + /* FIXME, we only do forwards playback, no trick modes yet */ + res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME, + flags, start_type, start, stop_type, stop); + + /* and block for the seek to complete */ + GST_INFO ("done seeking %d", res); + g_rec_mutex_unlock (&priv->state_lock); + + /* wait until pipeline is prerolled again, this will also collect stats */ + if (!wait_preroll (media)) + goto preroll_failed; + + g_rec_mutex_lock (&priv->state_lock); + GST_INFO ("prerolled again"); + } else { + GST_INFO ("no seek needed"); + res = TRUE; + } + g_rec_mutex_unlock (&priv->state_lock); + + return res; + + /* ERRORS */ +not_prepared: + { + g_rec_mutex_unlock (&priv->state_lock); + GST_INFO ("media %p is not prepared", media); + return FALSE; + } +not_seekable: + { + g_rec_mutex_unlock (&priv->state_lock); + GST_INFO ("pipeline is not seekable"); + return FALSE; + } +not_supported: + { + g_rec_mutex_unlock (&priv->state_lock); + GST_WARNING ("conversion to npt not supported"); + return FALSE; + } +preroll_failed: + { + GST_WARNING ("failed to preroll after seek"); + return FALSE; + } +} + +static void +stream_collect_blocking (GstRTSPStream * stream, gboolean * blocked) +{ + *blocked &= gst_rtsp_stream_is_blocking (stream); +} + +static gboolean +media_streams_blocking (GstRTSPMedia * media) +{ + gboolean blocking = TRUE; + + g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_blocking, + &blocking); + + return blocking; +} + +static GstStateChangeReturn +set_state (GstRTSPMedia * media, GstState state) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstStateChangeReturn ret; + + GST_INFO ("set state to %s for media %p", gst_element_state_get_name (state), + media); + ret = gst_element_set_state (priv->pipeline, state); + + return ret; +} + +static GstStateChangeReturn +set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstStateChangeReturn ret; + + GST_INFO ("set target state to %s for media %p", + gst_element_state_get_name (state), media); + priv->target_state = state; + + g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_TARGET_STATE], 0, + priv->target_state, NULL); + + if (do_state) + ret = set_state (media, state); + else + ret = GST_STATE_CHANGE_SUCCESS; + + return ret; +} + +/* called with state-lock */ +static gboolean +default_handle_message (GstRTSPMedia * media, GstMessage * message) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstMessageType type; + + type = GST_MESSAGE_TYPE (message); + + switch (type) { + case GST_MESSAGE_STATE_CHANGED: + break; + case GST_MESSAGE_BUFFERING: + { + gint percent; + + gst_message_parse_buffering (message, &percent); + + /* no state management needed for live pipelines */ + if (priv->is_live) + break; + + if (percent == 100) { + /* a 100% message means buffering is done */ + priv->buffering = FALSE; + /* if the desired state is playing, go back */ + if (priv->target_state == GST_STATE_PLAYING) { + GST_INFO ("Buffering done, setting pipeline to PLAYING"); + set_state (media, GST_STATE_PLAYING); + } else { + GST_INFO ("Buffering done"); + } + } else { + /* buffering busy */ + if (priv->buffering == FALSE) { + if (priv->target_state == GST_STATE_PLAYING) { + /* we were not buffering but PLAYING, PAUSE the pipeline. */ + GST_INFO ("Buffering, setting pipeline to PAUSED ..."); + set_state (media, GST_STATE_PAUSED); + } else { + GST_INFO ("Buffering ..."); + } + } + priv->buffering = TRUE; + } + break; + } + case GST_MESSAGE_LATENCY: + { + gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline)); + break; + } + case GST_MESSAGE_ERROR: + { + GError *gerror; + gchar *debug; + + gst_message_parse_error (message, &gerror, &debug); + GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug); + g_error_free (gerror); + g_free (debug); + + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR); + break; + } + case GST_MESSAGE_WARNING: + { + GError *gerror; + gchar *debug; + + gst_message_parse_warning (message, &gerror, &debug); + GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug); + g_error_free (gerror); + g_free (debug); + break; + } + case GST_MESSAGE_ELEMENT: + { + const GstStructure *s; + + s = gst_message_get_structure (message); + if (gst_structure_has_name (s, "GstRTSPStreamBlocking")) { + GST_DEBUG ("media received blocking message"); + if (priv->blocked && media_streams_blocking (media)) { + GST_DEBUG ("media is blocking"); + collect_media_stats (media); + + if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED); + } + } + break; + } + case GST_MESSAGE_STREAM_STATUS: + break; + case GST_MESSAGE_ASYNC_DONE: + if (priv->adding) { + /* when we are dynamically adding pads, the addition of the udpsrc will + * temporarily produce ASYNC_DONE messages. We have to ignore them and + * wait for the final ASYNC_DONE after everything prerolled */ + GST_INFO ("%p: ignoring ASYNC_DONE", media); + } else { + GST_INFO ("%p: got ASYNC_DONE", media); + collect_media_stats (media); + + if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED); + } + break; + case GST_MESSAGE_EOS: + GST_INFO ("%p: got EOS", media); + + if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) { + GST_DEBUG ("shutting down after EOS"); + finish_unprepare (media); + } + break; + default: + GST_INFO ("%p: got message type %d (%s)", media, type, + gst_message_type_get_name (type)); + break; + } + return TRUE; +} + +static gboolean +bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstRTSPMediaClass *klass; + gboolean ret; + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + + g_rec_mutex_lock (&priv->state_lock); + if (klass->handle_message) + ret = klass->handle_message (media, message); + else + ret = FALSE; + g_rec_mutex_unlock (&priv->state_lock); + + return ret; +} + +static void +watch_destroyed (GstRTSPMedia * media) +{ + GST_DEBUG_OBJECT (media, "source destroyed"); + g_object_unref (media); +} + +static GstElement * +find_payload_element (GstElement * payloader) +{ + GstElement *pay = NULL; + + if (GST_IS_BIN (payloader)) { + GstIterator *iter; + GValue item = { 0 }; + + iter = gst_bin_iterate_recurse (GST_BIN (payloader)); + while (gst_iterator_next (iter, &item) == GST_ITERATOR_OK) { + GstElement *element = (GstElement *) g_value_get_object (&item); + GstElementClass *eclass = GST_ELEMENT_GET_CLASS (element); + const gchar *klass; + + klass = + gst_element_class_get_metadata (eclass, GST_ELEMENT_METADATA_KLASS); + if (klass == NULL) + continue; + + if (strstr (klass, "Payloader") && strstr (klass, "RTP")) { + pay = gst_object_ref (element); + g_value_unset (&item); + break; + } + g_value_unset (&item); + } + gst_iterator_free (iter); + } else { + pay = g_object_ref (payloader); + } + + return pay; +} + +/* called from streaming threads */ +static void +pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstRTSPStream *stream; + GstElement *pay; + + /* find the real payload element */ + pay = find_payload_element (element); + stream = gst_rtsp_media_create_stream (media, pay, pad); + gst_object_unref (pay); + + GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream); + + g_rec_mutex_lock (&priv->state_lock); + if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARING) + goto not_preparing; + + g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream); + + /* we will be adding elements below that will cause ASYNC_DONE to be + * posted in the bus. We want to ignore those messages until the + * pipeline really prerolled. */ + priv->adding = TRUE; + + /* join the element in the PAUSED state because this callback is + * called from the streaming thread and it is PAUSED */ + if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline), + priv->rtpbin, GST_STATE_PAUSED)) { + GST_WARNING ("failed to join bin element"); + } + + priv->adding = FALSE; + g_rec_mutex_unlock (&priv->state_lock); + + return; + + /* ERRORS */ +not_preparing: + { + gst_rtsp_media_remove_stream (media, stream); + g_rec_mutex_unlock (&priv->state_lock); + GST_INFO ("ignore pad because we are not preparing"); + return; + } +} + +static void +pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstRTSPStream *stream; + + stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream"); + if (stream == NULL) + return; + + GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream); + + g_rec_mutex_lock (&priv->state_lock); + gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin); + g_rec_mutex_unlock (&priv->state_lock); + + gst_rtsp_media_remove_stream (media, stream); +} + +static void +remove_fakesink (GstRTSPMediaPrivate * priv) +{ + GstElement *fakesink; + + g_mutex_lock (&priv->lock); + if ((fakesink = priv->fakesink)) + gst_object_ref (fakesink); + priv->fakesink = NULL; + g_mutex_unlock (&priv->lock); + + if (fakesink) { + gst_bin_remove (GST_BIN (priv->pipeline), fakesink); + gst_element_set_state (fakesink, GST_STATE_NULL); + gst_object_unref (fakesink); + GST_INFO ("removed fakesink"); + } +} + +static void +no_more_pads_cb (GstElement * element, GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + + GST_INFO ("no more pads"); + remove_fakesink (priv); +} + +typedef struct _DynPaySignalHandlers DynPaySignalHandlers; + +struct _DynPaySignalHandlers +{ + gulong pad_added_handler; + gulong pad_removed_handler; + gulong no_more_pads_handler; +}; + +static gboolean +start_preroll (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstStateChangeReturn ret; + + GST_INFO ("setting pipeline to PAUSED for media %p", media); + /* first go to PAUSED */ + ret = set_target_state (media, GST_STATE_PAUSED, TRUE); + + switch (ret) { + case GST_STATE_CHANGE_SUCCESS: + GST_INFO ("SUCCESS state change for media %p", media); + priv->seekable = TRUE; + break; + case GST_STATE_CHANGE_ASYNC: + GST_INFO ("ASYNC state change for media %p", media); + priv->seekable = TRUE; + break; + case GST_STATE_CHANGE_NO_PREROLL: + /* we need to go to PLAYING */ + GST_INFO ("NO_PREROLL state change: live media %p", media); + /* FIXME we disable seeking for live streams for now. We should perform a + * seeking query in preroll instead */ + priv->seekable = FALSE; + priv->is_live = TRUE; + /* start blocked to make sure nothing goes to the sink */ + media_streams_set_blocked (media, TRUE); + ret = set_state (media, GST_STATE_PLAYING); + if (ret == GST_STATE_CHANGE_FAILURE) + goto state_failed; + break; + case GST_STATE_CHANGE_FAILURE: + goto state_failed; + } + + return TRUE; + +state_failed: + { + GST_WARNING ("failed to preroll pipeline"); + return FALSE; + } +} + +static gboolean +wait_preroll (GstRTSPMedia * media) +{ + GstRTSPMediaStatus status; + + GST_DEBUG ("wait to preroll pipeline"); + + /* wait until pipeline is prerolled */ + status = gst_rtsp_media_get_status (media); + if (status == GST_RTSP_MEDIA_STATUS_ERROR) + goto preroll_failed; + + return TRUE; + +preroll_failed: + { + GST_WARNING ("failed to preroll pipeline"); + return FALSE; + } +} + +static gboolean +start_prepare (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + guint i; + GList *walk; + + /* link streams we already have, other streams might appear when we have + * dynamic elements */ + for (i = 0; i < priv->streams->len; i++) { + GstRTSPStream *stream; + + stream = g_ptr_array_index (priv->streams, i); + + if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline), + priv->rtpbin, GST_STATE_NULL)) { + goto join_bin_failed; + } + } + + for (walk = priv->dynamic; walk; walk = g_list_next (walk)) { + GstElement *elem = walk->data; + DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers); + + GST_INFO ("adding callbacks for dynamic element %p", elem); + + handlers->pad_added_handler = g_signal_connect (elem, "pad-added", + (GCallback) pad_added_cb, media); + handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed", + (GCallback) pad_removed_cb, media); + handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads", + (GCallback) no_more_pads_cb, media); + + g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers); + + /* we add a fakesink here in order to make the state change async. We remove + * the fakesink again in the no-more-pads callback. */ + priv->fakesink = gst_element_factory_make ("fakesink", "fakesink"); + gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink); + } + + if (!start_preroll (media)) + goto preroll_failed; + + return FALSE; + +join_bin_failed: + { + GST_WARNING ("failed to join bin element"); + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR); + return FALSE; + } +preroll_failed: + { + GST_WARNING ("failed to preroll pipeline"); + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR); + return FALSE; + } +} + +static gboolean +default_prepare (GstRTSPMedia * media, GstRTSPThread * thread) +{ + GstRTSPMediaPrivate *priv; + GstRTSPMediaClass *klass; + GstBus *bus; + GMainContext *context; + GSource *source; + + priv = media->priv; + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + + if (!klass->create_rtpbin) + goto no_create_rtpbin; + + priv->rtpbin = klass->create_rtpbin (media); + if (priv->rtpbin != NULL) { + gboolean success = TRUE; + + if (klass->setup_rtpbin) + success = klass->setup_rtpbin (media, priv->rtpbin); + + if (success == FALSE) { + gst_object_unref (priv->rtpbin); + priv->rtpbin = NULL; + } + } + if (priv->rtpbin == NULL) + goto no_rtpbin; + + priv->thread = thread; + context = (thread != NULL) ? (thread->context) : NULL; + + bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline)); + + /* add the pipeline bus to our custom mainloop */ + priv->source = gst_bus_create_watch (bus); + gst_object_unref (bus); + + g_source_set_callback (priv->source, (GSourceFunc) bus_message, + g_object_ref (media), (GDestroyNotify) watch_destroyed); + + priv->id = g_source_attach (priv->source, context); + + /* add stuff to the bin */ + gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin); + + /* do remainder in context */ + source = g_idle_source_new (); + g_source_set_callback (source, (GSourceFunc) start_prepare, media, NULL); + g_source_attach (source, context); + g_source_unref (source); + + return TRUE; + + /* ERRORS */ +no_create_rtpbin: + { + GST_ERROR ("no create_rtpbin function"); + g_critical ("no create_rtpbin vmethod function set"); + return FALSE; + } +no_rtpbin: + { + GST_WARNING ("no rtpbin element"); + g_warning ("failed to create element 'rtpbin', check your installation"); + return FALSE; + } +} + +/** + * gst_rtsp_media_prepare: + * @media: a #GstRTSPMedia + * @thread: (transfer full) (allow-none): a #GstRTSPThread to run the + * bus handler or %NULL + * + * Prepare @media for streaming. This function will create the objects + * to manage the streaming. A pipeline must have been set on @media with + * gst_rtsp_media_take_pipeline(). + * + * It will preroll the pipeline and collect vital information about the streams + * such as the duration. + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread) +{ + GstRTSPMediaPrivate *priv; + GstRTSPMediaClass *klass; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + + priv = media->priv; + + g_rec_mutex_lock (&priv->state_lock); + priv->prepare_count++; + + if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED || + priv->status == GST_RTSP_MEDIA_STATUS_SUSPENDED) + goto was_prepared; + + if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) + goto is_preparing; + + if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED) + goto not_unprepared; + + if (!priv->reusable && priv->reused) + goto is_reused; + + GST_INFO ("preparing media %p", media); + + /* reset some variables */ + priv->is_live = FALSE; + priv->seekable = FALSE; + priv->buffering = FALSE; + + /* we're preparing now */ + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING); + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + if (klass->prepare) { + if (!klass->prepare (media, thread)) + goto prepare_failed; + } + +wait_status: + g_rec_mutex_unlock (&priv->state_lock); + + /* now wait for all pads to be prerolled, FIXME, we should somehow be + * able to do this async so that we don't block the server thread. */ + if (!wait_preroll (media)) + goto preroll_failed; + + g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL); + + GST_INFO ("object %p is prerolled", media); + + return TRUE; + + /* OK */ +is_preparing: + { + /* we are not going to use the giving thread, so stop it. */ + if (thread) + gst_rtsp_thread_stop (thread); + goto wait_status; + } +was_prepared: + { + GST_LOG ("media %p was prepared", media); + /* we are not going to use the giving thread, so stop it. */ + if (thread) + gst_rtsp_thread_stop (thread); + g_rec_mutex_unlock (&priv->state_lock); + return TRUE; + } + /* ERRORS */ +not_unprepared: + { + /* we are not going to use the giving thread, so stop it. */ + if (thread) + gst_rtsp_thread_stop (thread); + GST_WARNING ("media %p was not unprepared", media); + priv->prepare_count--; + g_rec_mutex_unlock (&priv->state_lock); + return FALSE; + } +is_reused: + { + /* we are not going to use the giving thread, so stop it. */ + if (thread) + gst_rtsp_thread_stop (thread); + priv->prepare_count--; + g_rec_mutex_unlock (&priv->state_lock); + GST_WARNING ("can not reuse media %p", media); + return FALSE; + } +prepare_failed: + { + /* we are not going to use the giving thread, so stop it. */ + if (thread) + gst_rtsp_thread_stop (thread); + priv->prepare_count--; + g_rec_mutex_unlock (&priv->state_lock); + GST_ERROR ("failed to prepare media"); + return FALSE; + } +preroll_failed: + { + GST_WARNING ("failed to preroll pipeline"); + gst_rtsp_media_unprepare (media); + return FALSE; + } +} + +/* must be called with state-lock */ +static void +finish_unprepare (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + gint i; + GList *walk; + + GST_DEBUG ("shutting down"); + + /* release the lock on shutdown, otherwise pad_added_cb might try to + * acquire the lock and then we deadlock */ + g_rec_mutex_unlock (&priv->state_lock); + set_state (media, GST_STATE_NULL); + g_rec_mutex_lock (&priv->state_lock); + remove_fakesink (priv); + + for (i = 0; i < priv->streams->len; i++) { + GstRTSPStream *stream; + + GST_INFO ("Removing elements of stream %d from pipeline", i); + + stream = g_ptr_array_index (priv->streams, i); + + gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin); + } + + /* remove the pad signal handlers */ + for (walk = priv->dynamic; walk; walk = g_list_next (walk)) { + GstElement *elem = walk->data; + DynPaySignalHandlers *handlers; + + handlers = + g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers"); + g_assert (handlers != NULL); + + g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler); + g_signal_handler_disconnect (G_OBJECT (elem), + handlers->pad_removed_handler); + g_signal_handler_disconnect (G_OBJECT (elem), + handlers->no_more_pads_handler); + + g_slice_free (DynPaySignalHandlers, handlers); + } + + gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin); + priv->rtpbin = NULL; + + if (priv->nettime) + gst_object_unref (priv->nettime); + priv->nettime = NULL; + + priv->reused = TRUE; + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARED); + + /* when the media is not reusable, this will effectively unref the media and + * recreate it */ + g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL); + + /* the source has the last ref to the media */ + if (priv->source) { + GST_DEBUG ("destroy source"); + g_source_destroy (priv->source); + g_source_unref (priv->source); + } + if (priv->thread) { + GST_DEBUG ("stop thread"); + gst_rtsp_thread_stop (priv->thread); + } +} + +/* called with state-lock */ +static gboolean +default_unprepare (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + + if (priv->eos_shutdown) { + GST_DEBUG ("sending EOS for shutdown"); + /* ref so that we don't disappear */ + gst_element_send_event (priv->pipeline, gst_event_new_eos ()); + /* we need to go to playing again for the EOS to propagate, normally in this + * state, nothing is receiving data from us anymore so this is ok. */ + set_state (media, GST_STATE_PLAYING); + } else { + finish_unprepare (media); + } + return TRUE; +} + +/** + * gst_rtsp_media_unprepare: + * @media: a #GstRTSPMedia + * + * Unprepare @media. After this call, the media should be prepared again before + * it can be used again. If the media is set to be non-reusable, a new instance + * must be created. + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_media_unprepare (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + gboolean success; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + + priv = media->priv; + + g_rec_mutex_lock (&priv->state_lock); + if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED) + goto was_unprepared; + + priv->prepare_count--; + if (priv->prepare_count > 0) + goto is_busy; + + GST_INFO ("unprepare media %p", media); + if (priv->blocked) + media_streams_set_blocked (media, FALSE); + set_target_state (media, GST_STATE_NULL, FALSE); + success = TRUE; + + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_UNPREPARING); + + if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) { + GstRTSPMediaClass *klass; + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + if (klass->unprepare) + success = klass->unprepare (media); + } else { + finish_unprepare (media); + } + g_rec_mutex_unlock (&priv->state_lock); + + return success; + +was_unprepared: + { + g_rec_mutex_unlock (&priv->state_lock); + GST_INFO ("media %p was already unprepared", media); + return TRUE; + } +is_busy: + { + GST_INFO ("media %p still prepared %d times", media, priv->prepare_count); + g_rec_mutex_unlock (&priv->state_lock); + return TRUE; + } +} + +/* should be called with state-lock */ +static GstClock * +get_clock_unlocked (GstRTSPMedia * media) +{ + if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) { + GST_DEBUG_OBJECT (media, "media was not prepared"); + return NULL; + } + return gst_pipeline_get_clock (GST_PIPELINE_CAST (media->priv->pipeline)); +} + +/** + * gst_rtsp_media_get_clock: + * @media: a #GstRTSPMedia + * + * Get the clock that is used by the pipeline in @media. + * + * @media must be prepared before this method returns a valid clock object. + * + * Returns: (transfer full): the #GstClock used by @media. unref after usage. + */ +GstClock * +gst_rtsp_media_get_clock (GstRTSPMedia * media) +{ + GstClock *clock; + GstRTSPMediaPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); + + priv = media->priv; + + g_rec_mutex_lock (&priv->state_lock); + clock = get_clock_unlocked (media); + g_rec_mutex_unlock (&priv->state_lock); + + return clock; +} + +/** + * gst_rtsp_media_get_base_time: + * @media: a #GstRTSPMedia + * + * Get the base_time that is used by the pipeline in @media. + * + * @media must be prepared before this method returns a valid base_time. + * + * Returns: the base_time used by @media. + */ +GstClockTime +gst_rtsp_media_get_base_time (GstRTSPMedia * media) +{ + GstClockTime result; + GstRTSPMediaPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_CLOCK_TIME_NONE); + + priv = media->priv; + + g_rec_mutex_lock (&priv->state_lock); + if (media->priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) + goto not_prepared; + + result = gst_element_get_base_time (media->priv->pipeline); + g_rec_mutex_unlock (&priv->state_lock); + + return result; + + /* ERRORS */ +not_prepared: + { + g_rec_mutex_unlock (&priv->state_lock); + GST_DEBUG_OBJECT (media, "media was not prepared"); + return GST_CLOCK_TIME_NONE; + } +} + +/** + * gst_rtsp_media_get_time_provider: + * @media: a #GstRTSPMedia + * @address: (allow-none): an address or %NULL + * @port: a port or 0 + * + * Get the #GstNetTimeProvider for the clock used by @media. The time provider + * will listen on @address and @port for client time requests. + * + * Returns: (transfer full): the #GstNetTimeProvider of @media. + */ +GstNetTimeProvider * +gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address, + guint16 port) +{ + GstRTSPMediaPrivate *priv; + GstNetTimeProvider *provider = NULL; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); + + priv = media->priv; + + g_rec_mutex_lock (&priv->state_lock); + if (priv->time_provider) { + if ((provider = priv->nettime) == NULL) { + GstClock *clock; + + if (priv->time_provider && (clock = get_clock_unlocked (media))) { + provider = gst_net_time_provider_new (clock, address, port); + gst_object_unref (clock); + + priv->nettime = provider; + } + } + } + g_rec_mutex_unlock (&priv->state_lock); + + if (provider) + gst_object_ref (provider); + + return provider; +} + +static gboolean +default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, GstSDPInfo * info) +{ + return gst_rtsp_sdp_from_media (sdp, info, media); +} + +/** + * gst_rtsp_media_setup_sdp: + * @media: a #GstRTSPMedia + * @sdp: (transfer none): a #GstSDPMessage + * @info: (transfer none): a #GstSDPInfo + * + * Add @media specific info to @sdp. @info is used to configure the connection + * information in the SDP. + * + * Returns: TRUE on success. + */ +gboolean +gst_rtsp_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, + GstSDPInfo * info) +{ + GstRTSPMediaPrivate *priv; + GstRTSPMediaClass *klass; + gboolean res; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + g_return_val_if_fail (sdp != NULL, FALSE); + g_return_val_if_fail (info != NULL, FALSE); + + priv = media->priv; + + g_rec_mutex_lock (&priv->state_lock); + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + + if (!klass->setup_sdp) + goto no_setup_sdp; + + res = klass->setup_sdp (media, sdp, info); + + g_rec_mutex_unlock (&priv->state_lock); + + return res; + + /* ERRORS */ +no_setup_sdp: + { + g_rec_mutex_unlock (&priv->state_lock); + GST_ERROR ("no setup_sdp function"); + g_critical ("no setup_sdp vmethod function set"); + return FALSE; + } +} + +static void +do_set_seqnum (GstRTSPStream * stream) +{ + guint16 seq_num; + seq_num = gst_rtsp_stream_get_current_seqnum (stream); + gst_rtsp_stream_set_seqnum_offset (stream, seq_num + 1); +} + +/* call with state_lock */ +gboolean +default_suspend (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstStateChangeReturn ret; + + switch (priv->suspend_mode) { + case GST_RTSP_SUSPEND_MODE_NONE: + GST_DEBUG ("media %p no suspend", media); + break; + case GST_RTSP_SUSPEND_MODE_PAUSE: + GST_DEBUG ("media %p suspend to PAUSED", media); + ret = set_target_state (media, GST_STATE_PAUSED, TRUE); + if (ret == GST_STATE_CHANGE_FAILURE) + goto state_failed; + break; + case GST_RTSP_SUSPEND_MODE_RESET: + GST_DEBUG ("media %p suspend to NULL", media); + ret = set_target_state (media, GST_STATE_NULL, TRUE); + if (ret == GST_STATE_CHANGE_FAILURE) + goto state_failed; + /* Because payloader needs to set the sequence number as + * monotonic, we need to preserve the sequence number + * after pause. (otherwise going from pause to play, which + * is actually from NULL to PLAY will create a new sequence + * number. */ + g_ptr_array_foreach (priv->streams, (GFunc) do_set_seqnum, NULL); + break; + default: + break; + } + + /* let the streams do the state changes freely, if any */ + media_streams_set_blocked (media, FALSE); + + return TRUE; + + /* ERRORS */ +state_failed: + { + GST_WARNING ("failed changing pipeline's state for media %p", media); + return FALSE; + } +} + +/** + * gst_rtsp_media_suspend: + * @media: a #GstRTSPMedia + * + * Suspend @media. The state of the pipeline managed by @media is set to + * GST_STATE_NULL but all streams are kept. @media can be prepared again + * with gst_rtsp_media_unsuspend() + * + * @media must be prepared with gst_rtsp_media_prepare(); + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_media_suspend (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstRTSPMediaClass *klass; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + + GST_FIXME ("suspend for dynamic pipelines needs fixing"); + + g_rec_mutex_lock (&priv->state_lock); + if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) + goto not_prepared; + + /* don't attempt to suspend when something is busy */ + if (priv->n_active > 0) + goto done; + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + if (klass->suspend) { + if (!klass->suspend (media)) + goto suspend_failed; + } + + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_SUSPENDED); +done: + g_rec_mutex_unlock (&priv->state_lock); + + return TRUE; + + /* ERRORS */ +not_prepared: + { + g_rec_mutex_unlock (&priv->state_lock); + GST_WARNING ("media %p was not prepared", media); + return FALSE; + } +suspend_failed: + { + g_rec_mutex_unlock (&priv->state_lock); + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR); + GST_WARNING ("failed to suspend media %p", media); + return FALSE; + } +} + +/* call with state_lock */ +gboolean +default_unsuspend (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + + switch (priv->suspend_mode) { + case GST_RTSP_SUSPEND_MODE_NONE: + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED); + break; + case GST_RTSP_SUSPEND_MODE_PAUSE: + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED); + break; + case GST_RTSP_SUSPEND_MODE_RESET: + { + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING); + if (!start_preroll (media)) + goto start_failed; + g_rec_mutex_unlock (&priv->state_lock); + + if (!wait_preroll (media)) + goto preroll_failed; + + g_rec_mutex_lock (&priv->state_lock); + } + default: + break; + } + + return TRUE; + + /* ERRORS */ +start_failed: + { + GST_WARNING ("failed to preroll pipeline"); + return FALSE; + } +preroll_failed: + { + GST_WARNING ("failed to preroll pipeline"); + return FALSE; + } +} + +/** + * gst_rtsp_media_unsuspend: + * @media: a #GstRTSPMedia + * + * Unsuspend @media if it was in a suspended state. This method does nothing + * when the media was not in the suspended state. + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_media_unsuspend (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstRTSPMediaClass *klass; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + + g_rec_mutex_lock (&priv->state_lock); + if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED) + goto done; + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + if (klass->unsuspend) { + if (!klass->unsuspend (media)) + goto unsuspend_failed; + } + +done: + g_rec_mutex_unlock (&priv->state_lock); + + return TRUE; + + /* ERRORS */ +unsuspend_failed: + { + g_rec_mutex_unlock (&priv->state_lock); + GST_WARNING ("failed to unsuspend media %p", media); + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR); + return FALSE; + } +} + +/* must be called with state-lock */ +static void +media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state) +{ + GstRTSPMediaPrivate *priv = media->priv; + + if (state == GST_STATE_NULL) { + gst_rtsp_media_unprepare (media); + } else { + GST_INFO ("state %s media %p", gst_element_state_get_name (state), media); + set_target_state (media, state, FALSE); + /* when we are buffering, don't update the state yet, this will be done + * when buffering finishes */ + if (priv->buffering) { + GST_INFO ("Buffering busy, delay state change"); + } else { + if (state == GST_STATE_PLAYING) + /* make sure pads are not blocking anymore when going to PLAYING */ + media_streams_set_blocked (media, FALSE); + + set_state (media, state); + + /* and suspend after pause */ + if (state == GST_STATE_PAUSED) + gst_rtsp_media_suspend (media); + } + } +} + +/** + * gst_rtsp_media_set_pipeline_state: + * @media: a #GstRTSPMedia + * @state: the target state of the pipeline + * + * Set the state of the pipeline managed by @media to @state + */ +void +gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstState state) +{ + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + g_rec_mutex_lock (&media->priv->state_lock); + media_set_pipeline_state_locked (media, state); + g_rec_mutex_unlock (&media->priv->state_lock); +} + +/** + * gst_rtsp_media_set_state: + * @media: a #GstRTSPMedia + * @state: the target state of the media + * @transports: (transfer none) (element-type GstRtspServer.RTSPStreamTransport): + * a #GPtrArray of #GstRTSPStreamTransport pointers + * + * Set the state of @media to @state and for the transports in @transports. + * + * @media must be prepared with gst_rtsp_media_prepare(); + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state, + GPtrArray * transports) +{ + GstRTSPMediaPrivate *priv; + gint i; + gboolean activate, deactivate, do_state; + gint old_active; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + g_return_val_if_fail (transports != NULL, FALSE); + + priv = media->priv; + + g_rec_mutex_lock (&priv->state_lock); + if (priv->status == GST_RTSP_MEDIA_STATUS_ERROR) + goto error_status; + if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED && + priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED) + goto not_prepared; + + /* NULL and READY are the same */ + if (state == GST_STATE_READY) + state = GST_STATE_NULL; + + activate = deactivate = FALSE; + + GST_INFO ("going to state %s media %p", gst_element_state_get_name (state), + media); + + switch (state) { + case GST_STATE_NULL: + case GST_STATE_PAUSED: + /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */ + if (priv->target_state == GST_STATE_PLAYING) + deactivate = TRUE; + break; + case GST_STATE_PLAYING: + /* we're going to PLAYING, activate */ + activate = TRUE; + break; + default: + break; + } + old_active = priv->n_active; + + for (i = 0; i < transports->len; i++) { + GstRTSPStreamTransport *trans; + + /* we need a non-NULL entry in the array */ + trans = g_ptr_array_index (transports, i); + if (trans == NULL) + continue; + + if (activate) { + if (gst_rtsp_stream_transport_set_active (trans, TRUE)) + priv->n_active++; + } else if (deactivate) { + if (gst_rtsp_stream_transport_set_active (trans, FALSE)) + priv->n_active--; + } + } + + /* we just activated the first media, do the playing state change */ + if (old_active == 0 && activate) + do_state = TRUE; + /* if we have no more active media, do the downward state changes */ + else if (priv->n_active == 0) + do_state = TRUE; + else + do_state = FALSE; + + GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active, + media, do_state); + + if (priv->target_state != state) { + if (do_state) + media_set_pipeline_state_locked (media, state); + + g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state, + NULL); + } + + /* remember where we are */ + if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED || + old_active != priv->n_active)) + collect_media_stats (media); + + g_rec_mutex_unlock (&priv->state_lock); + + return TRUE; + + /* ERRORS */ +not_prepared: + { + GST_WARNING ("media %p was not prepared", media); + g_rec_mutex_unlock (&priv->state_lock); + return FALSE; + } +error_status: + { + GST_WARNING ("media %p in error status while changing to state %d", + media, state); + if (state == GST_STATE_NULL) { + for (i = 0; i < transports->len; i++) { + GstRTSPStreamTransport *trans; + + /* we need a non-NULL entry in the array */ + trans = g_ptr_array_index (transports, i); + if (trans == NULL) + continue; + + gst_rtsp_stream_transport_set_active (trans, FALSE); + } + priv->n_active = 0; + } + g_rec_mutex_unlock (&priv->state_lock); + return FALSE; + } +} diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h new file mode 100644 index 0000000..a78650d --- /dev/null +++ b/gst/rtsp-server/rtsp-media.h @@ -0,0 +1,235 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include +#include +#include +#include + +#ifndef __GST_RTSP_MEDIA_H__ +#define __GST_RTSP_MEDIA_H__ + +G_BEGIN_DECLS + +/* types for the media */ +#define GST_TYPE_RTSP_MEDIA (gst_rtsp_media_get_type ()) +#define GST_IS_RTSP_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_MEDIA)) +#define GST_IS_RTSP_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_MEDIA)) +#define GST_RTSP_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_MEDIA, GstRTSPMediaClass)) +#define GST_RTSP_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_MEDIA, GstRTSPMedia)) +#define GST_RTSP_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_MEDIA, GstRTSPMediaClass)) +#define GST_RTSP_MEDIA_CAST(obj) ((GstRTSPMedia*)(obj)) +#define GST_RTSP_MEDIA_CLASS_CAST(klass) ((GstRTSPMediaClass*)(klass)) + +typedef struct _GstRTSPMedia GstRTSPMedia; +typedef struct _GstRTSPMediaClass GstRTSPMediaClass; +typedef struct _GstRTSPMediaPrivate GstRTSPMediaPrivate; + +/** + * GstRTSPMediaStatus: + * @GST_RTSP_MEDIA_STATUS_UNPREPARED: media pipeline not prerolled + * @GST_RTSP_MEDIA_STATUS_UNPREPARING: media pipeline is busy doing a clean + * shutdown. + * @GST_RTSP_MEDIA_STATUS_PREPARING: media pipeline is prerolling + * @GST_RTSP_MEDIA_STATUS_PREPARED: media pipeline is prerolled + * @GST_RTSP_MEDIA_STATUS_SUSPENDED: media is suspended + * @GST_RTSP_MEDIA_STATUS_ERROR: media pipeline is in error + * + * The state of the media pipeline. + */ +typedef enum { + GST_RTSP_MEDIA_STATUS_UNPREPARED = 0, + GST_RTSP_MEDIA_STATUS_UNPREPARING = 1, + GST_RTSP_MEDIA_STATUS_PREPARING = 2, + GST_RTSP_MEDIA_STATUS_PREPARED = 3, + GST_RTSP_MEDIA_STATUS_SUSPENDED = 4, + GST_RTSP_MEDIA_STATUS_ERROR = 5 +} GstRTSPMediaStatus; + +/** + * GstRTSPSuspendMode: + * @GST_RTSP_SUSPEND_MODE_NONE: Media is not suspended + * @GST_RTSP_SUSPEND_MODE_PAUSE: Media is PAUSED in suspend + * @GST_RTSP_SUSPEND_MODE_RESET: The media is set to NULL when suspended + * + * The suspend mode of the media pipeline. A media pipeline is suspended right + * after creating the SDP and when the client performs a PAUSED request. + */ +typedef enum { + GST_RTSP_SUSPEND_MODE_NONE = 0, + GST_RTSP_SUSPEND_MODE_PAUSE = 1, + GST_RTSP_SUSPEND_MODE_RESET = 2 +} GstRTSPSuspendMode; + +#define GST_TYPE_RTSP_SUSPEND_MODE (gst_rtsp_suspend_mode_get_type()) +GType gst_rtsp_suspend_mode_get_type (void); + +#include "rtsp-stream.h" +#include "rtsp-thread-pool.h" +#include "rtsp-permissions.h" +#include "rtsp-address-pool.h" +#include "rtsp-sdp.h" + +/** + * GstRTSPMedia: + * + * A class that contains the GStreamer element along with a list of + * #GstRTSPStream objects that can produce data. + * + * This object is usually created from a #GstRTSPMediaFactory. + */ +struct _GstRTSPMedia { + GObject parent; + + /*< private >*/ + GstRTSPMediaPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPMediaClass: + * @handle_message: handle a message + * @prepare: the default implementation adds all elements and sets the + * pipeline's state to GST_STATE_PAUSED (or GST_STATE_PLAYING + * in case of NO_PREROLL elements). + * @unprepare: the default implementation sets the pipeline's state + * to GST_STATE_NULL and removes all elements. + * @suspend: the default implementation sets the pipeline's state to + * GST_STATE_NULL GST_STATE_PAUSED depending on the selected + * suspend mode. + * @unsuspend: the default implementation reverts the suspend operation. + * The pipeline will be prerolled again if it's state was + * set to GST_STATE_NULL in suspend. + * @convert_range: convert a range to the given unit + * @query_position: query the current position in the pipeline + * @query_stop: query when playback will stop + * + * The RTSP media class + */ +struct _GstRTSPMediaClass { + GObjectClass parent_class; + + /* vmethods */ + gboolean (*handle_message) (GstRTSPMedia *media, GstMessage *message); + gboolean (*prepare) (GstRTSPMedia *media, GstRTSPThread *thread); + gboolean (*unprepare) (GstRTSPMedia *media); + gboolean (*suspend) (GstRTSPMedia *media); + gboolean (*unsuspend) (GstRTSPMedia *media); + gboolean (*convert_range) (GstRTSPMedia *media, GstRTSPTimeRange *range, + GstRTSPRangeUnit unit); + gboolean (*query_position) (GstRTSPMedia *media, gint64 *position); + gboolean (*query_stop) (GstRTSPMedia *media, gint64 *stop); + GstElement * (*create_rtpbin) (GstRTSPMedia *media); + gboolean (*setup_rtpbin) (GstRTSPMedia *media, GstElement *rtpbin); + gboolean (*setup_sdp) (GstRTSPMedia *media, GstSDPMessage *sdp, GstSDPInfo *info); + + /* signals */ + void (*new_stream) (GstRTSPMedia *media, GstRTSPStream * stream); + void (*removed_stream) (GstRTSPMedia *media, GstRTSPStream * stream); + + void (*prepared) (GstRTSPMedia *media); + void (*unprepared) (GstRTSPMedia *media); + + void (*target_state) (GstRTSPMedia *media, GstState state); + void (*new_state) (GstRTSPMedia *media, GstState state); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +GType gst_rtsp_media_get_type (void); + +/* creating the media */ +GstRTSPMedia * gst_rtsp_media_new (GstElement *element); +GstElement * gst_rtsp_media_get_element (GstRTSPMedia *media); + +void gst_rtsp_media_take_pipeline (GstRTSPMedia *media, GstPipeline *pipeline); + +GstRTSPMediaStatus gst_rtsp_media_get_status (GstRTSPMedia *media); + +void gst_rtsp_media_set_permissions (GstRTSPMedia *media, + GstRTSPPermissions *permissions); +GstRTSPPermissions * gst_rtsp_media_get_permissions (GstRTSPMedia *media); + +void gst_rtsp_media_set_shared (GstRTSPMedia *media, gboolean shared); +gboolean gst_rtsp_media_is_shared (GstRTSPMedia *media); + +void gst_rtsp_media_set_reusable (GstRTSPMedia *media, gboolean reusable); +gboolean gst_rtsp_media_is_reusable (GstRTSPMedia *media); + +void gst_rtsp_media_set_profiles (GstRTSPMedia *media, GstRTSPProfile profiles); +GstRTSPProfile gst_rtsp_media_get_profiles (GstRTSPMedia *media); + +void gst_rtsp_media_set_protocols (GstRTSPMedia *media, GstRTSPLowerTrans protocols); +GstRTSPLowerTrans gst_rtsp_media_get_protocols (GstRTSPMedia *media); + +void gst_rtsp_media_set_eos_shutdown (GstRTSPMedia *media, gboolean eos_shutdown); +gboolean gst_rtsp_media_is_eos_shutdown (GstRTSPMedia *media); + +void gst_rtsp_media_set_address_pool (GstRTSPMedia *media, GstRTSPAddressPool *pool); +GstRTSPAddressPool * gst_rtsp_media_get_address_pool (GstRTSPMedia *media); + +void gst_rtsp_media_set_buffer_size (GstRTSPMedia *media, guint size); +guint gst_rtsp_media_get_buffer_size (GstRTSPMedia *media); + +void gst_rtsp_media_use_time_provider (GstRTSPMedia *media, gboolean time_provider); +gboolean gst_rtsp_media_is_time_provider (GstRTSPMedia *media); +GstNetTimeProvider * gst_rtsp_media_get_time_provider (GstRTSPMedia *media, + const gchar *address, guint16 port); + +/* prepare the media for playback */ +gboolean gst_rtsp_media_prepare (GstRTSPMedia *media, GstRTSPThread *thread); +gboolean gst_rtsp_media_unprepare (GstRTSPMedia *media); + +void gst_rtsp_media_set_suspend_mode (GstRTSPMedia *media, GstRTSPSuspendMode mode); +GstRTSPSuspendMode gst_rtsp_media_get_suspend_mode (GstRTSPMedia *media); + +gboolean gst_rtsp_media_suspend (GstRTSPMedia *media); +gboolean gst_rtsp_media_unsuspend (GstRTSPMedia *media); + +gboolean gst_rtsp_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, + GstSDPInfo * info); + +/* creating streams */ +void gst_rtsp_media_collect_streams (GstRTSPMedia *media); +GstRTSPStream * gst_rtsp_media_create_stream (GstRTSPMedia *media, + GstElement *payloader, + GstPad *srcpad); + +/* dealing with the media */ +GstClock * gst_rtsp_media_get_clock (GstRTSPMedia *media); +GstClockTime gst_rtsp_media_get_base_time (GstRTSPMedia *media); + +guint gst_rtsp_media_n_streams (GstRTSPMedia *media); +GstRTSPStream * gst_rtsp_media_get_stream (GstRTSPMedia *media, guint idx); +GstRTSPStream * gst_rtsp_media_find_stream (GstRTSPMedia *media, const gchar * control); + +gboolean gst_rtsp_media_seek (GstRTSPMedia *media, GstRTSPTimeRange *range); +gchar * gst_rtsp_media_get_range_string (GstRTSPMedia *media, + gboolean play, + GstRTSPRangeUnit unit); + +gboolean gst_rtsp_media_set_state (GstRTSPMedia *media, GstState state, + GPtrArray *transports); +void gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, + GstState state); + +G_END_DECLS + +#endif /* __GST_RTSP_MEDIA_H__ */ diff --git a/gst/rtsp-server/rtsp-mount-points.c b/gst/rtsp-server/rtsp-mount-points.c new file mode 100644 index 0000000..c6a8c06 --- /dev/null +++ b/gst/rtsp-server/rtsp-mount-points.c @@ -0,0 +1,370 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-mount-points + * @short_description: Map a path to media + * @see_also: #GstRTSPMediaFactory, #GstRTSPClient + * + * A #GstRTSPMountPoints object maintains a relation between paths + * and #GstRTSPMediaFactory objects. This object is usually given to + * #GstRTSPClient and used to find the media attached to a path. + * + * With gst_rtsp_mount_points_add_factory () and + * gst_rtsp_mount_points_remove_factory(), factories can be added and + * removed. + * + * With gst_rtsp_mount_points_match() you can find the #GstRTSPMediaFactory + * object that completely matches the given path. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ +#include + +#include "rtsp-mount-points.h" + +#define GST_RTSP_MOUNT_POINTS_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MOUNT_POINTS, GstRTSPMountPointsPrivate)) + +typedef struct +{ + gchar *path; + gint len; + GstRTSPMediaFactory *factory; +} DataItem; + +static DataItem * +data_item_new (gchar * path, gint len, GstRTSPMediaFactory * factory) +{ + DataItem *item; + + item = g_slice_alloc (sizeof (DataItem)); + item->path = path; + item->len = len; + item->factory = factory; + + return item; +} + +static void +data_item_free (gpointer data) +{ + DataItem *item = data; + + g_free (item->path); + g_object_unref (item->factory); + g_slice_free1 (sizeof (DataItem), item); +} + +static void +data_item_dump (gconstpointer a, gconstpointer prefix) +{ + const DataItem *item = a; + + GST_DEBUG ("%s%s %p", (gchar *) prefix, item->path, item->factory); +} + +static gint +data_item_compare (gconstpointer a, gconstpointer b, gpointer user_data) +{ + const DataItem *item1 = a, *item2 = b; + gint res; + + res = g_strcmp0 (item1->path, item2->path); + + return res; +} + +struct _GstRTSPMountPointsPrivate +{ + GMutex lock; + GSequence *mounts; /* protected by lock */ + gboolean dirty; +}; + +G_DEFINE_TYPE (GstRTSPMountPoints, gst_rtsp_mount_points, G_TYPE_OBJECT); + +GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug); +#define GST_CAT_DEFAULT rtsp_media_debug + +static gchar *default_make_path (GstRTSPMountPoints * mounts, + const GstRTSPUrl * url); +static void gst_rtsp_mount_points_finalize (GObject * obj); + +static void +gst_rtsp_mount_points_class_init (GstRTSPMountPointsClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPMountPointsPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = gst_rtsp_mount_points_finalize; + + klass->make_path = default_make_path; + + GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmountpoints", 0, + "GstRTSPMountPoints"); +} + +static void +gst_rtsp_mount_points_init (GstRTSPMountPoints * mounts) +{ + GstRTSPMountPointsPrivate *priv = GST_RTSP_MOUNT_POINTS_GET_PRIVATE (mounts); + + GST_DEBUG_OBJECT (mounts, "created"); + + mounts->priv = priv; + + g_mutex_init (&priv->lock); + priv->mounts = g_sequence_new (data_item_free); + priv->dirty = FALSE; +} + +static void +gst_rtsp_mount_points_finalize (GObject * obj) +{ + GstRTSPMountPoints *mounts = GST_RTSP_MOUNT_POINTS (obj); + GstRTSPMountPointsPrivate *priv = mounts->priv; + + GST_DEBUG_OBJECT (mounts, "finalized"); + + g_sequence_free (priv->mounts); + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (gst_rtsp_mount_points_parent_class)->finalize (obj); +} + +/** + * gst_rtsp_mount_points_new: + * + * Make a new mount points object. + * + * Returns: (transfer full): a new #GstRTSPMountPoints + */ +GstRTSPMountPoints * +gst_rtsp_mount_points_new (void) +{ + GstRTSPMountPoints *result; + + result = g_object_new (GST_TYPE_RTSP_MOUNT_POINTS, NULL); + + return result; +} + +static gchar * +default_make_path (GstRTSPMountPoints * mounts, const GstRTSPUrl * url) +{ + return g_strdup (url->abspath); +} + +/** + * gst_rtsp_mount_points_make_path: + * @mounts: a #GstRTSPMountPoints + * @url: a #GstRTSPUrl + * + * Make a path string from @url. + * + * Returns: (transfer full): a path string for @url, g_free() after usage. + */ +gchar * +gst_rtsp_mount_points_make_path (GstRTSPMountPoints * mounts, + const GstRTSPUrl * url) +{ + GstRTSPMountPointsClass *klass; + gchar *result; + + g_return_val_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts), NULL); + g_return_val_if_fail (url != NULL, NULL); + + klass = GST_RTSP_MOUNT_POINTS_GET_CLASS (mounts); + + if (klass->make_path) + result = klass->make_path (mounts, url); + else + result = NULL; + + return result; +} + +static gboolean +has_prefix (DataItem * str, DataItem * prefix) +{ + /* prefix needs to be smaller than str */ + if (str->len < prefix->len) + return FALSE; + + /* if str is larger, it there should be a / following the prefix */ + if (str->len > prefix->len && str->path[prefix->len] != '/') + return FALSE; + + return strncmp (str->path, prefix->path, prefix->len) == 0; +} + +/** + * gst_rtsp_mount_points_match: + * @mounts: a #GstRTSPMountPoints + * @path: a mount point + * @matched: (out) (allow-none): the amount of @path matched + * + * Find the factory in @mounts that has the longest match with @path. + * + * If @matched is %NULL, @path will match the factory exactly otherwise + * the amount of characters that matched is returned in @matched. + * + * Returns: (transfer full): the #GstRTSPMediaFactory for @path. + * g_object_unref() after usage. + */ +GstRTSPMediaFactory * +gst_rtsp_mount_points_match (GstRTSPMountPoints * mounts, + const gchar * path, gint * matched) +{ + GstRTSPMountPointsPrivate *priv; + GstRTSPMediaFactory *result = NULL; + GSequenceIter *iter, *best; + DataItem item, *ritem; + + g_return_val_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts), NULL); + g_return_val_if_fail (path != NULL, NULL); + + priv = mounts->priv; + + item.path = (gchar *) path; + item.len = strlen (path); + + g_mutex_lock (&priv->lock); + if (priv->dirty) { + g_sequence_sort (priv->mounts, data_item_compare, mounts); + g_sequence_foreach (priv->mounts, (GFunc) data_item_dump, + (gpointer) "sort :"); + priv->dirty = FALSE; + } + + /* find the location of the media in the hashtable we only use the absolute + * path of the uri to find a media factory. If the factory depends on other + * properties found in the url, this method should be overridden. */ + iter = g_sequence_get_begin_iter (priv->mounts); + best = NULL; + while (!g_sequence_iter_is_end (iter)) { + ritem = g_sequence_get (iter); + + data_item_dump (ritem, "inspect: "); + + if (best == NULL) { + if (has_prefix (&item, ritem)) { + data_item_dump (ritem, "prefix: "); + best = iter; + } + } else { + if (!has_prefix (&item, ritem)) + break; + + best = iter; + data_item_dump (ritem, "new best: "); + } + iter = g_sequence_iter_next (iter); + } + if (best) { + ritem = g_sequence_get (best); + data_item_dump (ritem, "result: "); + if (matched || ritem->len == item.len) { + result = g_object_ref (ritem->factory); + if (matched) + *matched = ritem->len; + } + } + g_mutex_unlock (&priv->lock); + + GST_INFO ("found media factory %p for path %s", result, path); + + return result; +} + +/** + * gst_rtsp_mount_points_add_factory: + * @mounts: a #GstRTSPMountPoints + * @path: a mount point + * @factory: (transfer full): a #GstRTSPMediaFactory + * + * Attach @factory to the mount point @path in @mounts. + * + * @path is of the form (/node)+. Any previous mount point will be freed. + * + * Ownership is taken of the reference on @factory so that @factory should not be + * used after calling this function. + */ +void +gst_rtsp_mount_points_add_factory (GstRTSPMountPoints * mounts, + const gchar * path, GstRTSPMediaFactory * factory) +{ + GstRTSPMountPointsPrivate *priv; + DataItem *item; + + g_return_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts)); + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + g_return_if_fail (path != NULL); + + priv = mounts->priv; + + item = data_item_new (g_strdup (path), strlen (path), factory); + + GST_INFO ("adding media factory %p for path %s", factory, path); + + g_mutex_lock (&priv->lock); + g_sequence_append (priv->mounts, item); + priv->dirty = TRUE; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_mount_points_remove_factory: + * @mounts: a #GstRTSPMountPoints + * @path: a mount point + * + * Remove the #GstRTSPMediaFactory associated with @path in @mounts. + */ +void +gst_rtsp_mount_points_remove_factory (GstRTSPMountPoints * mounts, + const gchar * path) +{ + GstRTSPMountPointsPrivate *priv; + DataItem item; + GSequenceIter *iter; + + g_return_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts)); + g_return_if_fail (path != NULL); + + priv = mounts->priv; + + item.path = (gchar *) path; + + GST_INFO ("removing media factory for path %s", path); + + g_mutex_lock (&priv->lock); + if (priv->dirty) { + g_sequence_sort (priv->mounts, data_item_compare, mounts); + priv->dirty = FALSE; + } + iter = g_sequence_lookup (priv->mounts, &item, data_item_compare, mounts); + if (iter) { + g_sequence_remove (iter); + priv->dirty = TRUE; + } + g_mutex_unlock (&priv->lock); +} diff --git a/gst/rtsp-server/rtsp-mount-points.h b/gst/rtsp-server/rtsp-mount-points.h new file mode 100644 index 0000000..ed13d59 --- /dev/null +++ b/gst/rtsp-server/rtsp-mount-points.h @@ -0,0 +1,91 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include "rtsp-media-factory.h" + +#ifndef __GST_RTSP_MOUNT_POINTS_H__ +#define __GST_RTSP_MOUNT_POINTS_H__ + +G_BEGIN_DECLS + +#define GST_TYPE_RTSP_MOUNT_POINTS (gst_rtsp_mount_points_get_type ()) +#define GST_IS_RTSP_MOUNT_POINTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_MOUNT_POINTS)) +#define GST_IS_RTSP_MOUNT_POINTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_MOUNT_POINTS)) +#define GST_RTSP_MOUNT_POINTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_MOUNT_POINTS, GstRTSPMountPointsClass)) +#define GST_RTSP_MOUNT_POINTS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_MOUNT_POINTS, GstRTSPMountPoints)) +#define GST_RTSP_MOUNT_POINTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_MOUNT_POINTS, GstRTSPMountPointsClass)) +#define GST_RTSP_MOUNT_POINTS_CAST(obj) ((GstRTSPMountPoints*)(obj)) +#define GST_RTSP_MOUNT_POINTS_CLASS_CAST(klass) ((GstRTSPMountPointsClass*)(klass)) + +typedef struct _GstRTSPMountPoints GstRTSPMountPoints; +typedef struct _GstRTSPMountPointsClass GstRTSPMountPointsClass; +typedef struct _GstRTSPMountPointsPrivate GstRTSPMountPointsPrivate; + +/** + * GstRTSPMountPoints: + * + * Creates a #GstRTSPMediaFactory object for a given url. + */ +struct _GstRTSPMountPoints { + GObject parent; + + /*< private >*/ + GstRTSPMountPointsPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPMountPointsClass: + * @make_path: make a path from the given url. + * + * The class for the media mounts object. + */ +struct _GstRTSPMountPointsClass { + GObjectClass parent_class; + + gchar * (*make_path) (GstRTSPMountPoints *mounts, + const GstRTSPUrl *url); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_rtsp_mount_points_get_type (void); + +/* creating a mount points */ +GstRTSPMountPoints * gst_rtsp_mount_points_new (void); + +gchar * gst_rtsp_mount_points_make_path (GstRTSPMountPoints *mounts, + const GstRTSPUrl * url); +/* finding a media factory */ +GstRTSPMediaFactory * gst_rtsp_mount_points_match (GstRTSPMountPoints *mounts, + const gchar *path, + gint * matched); +/* managing media to a mount point */ +void gst_rtsp_mount_points_add_factory (GstRTSPMountPoints *mounts, + const gchar *path, + GstRTSPMediaFactory *factory); +void gst_rtsp_mount_points_remove_factory (GstRTSPMountPoints *mounts, + const gchar *path); + +G_END_DECLS + +#endif /* __GST_RTSP_MOUNT_POINTS_H__ */ diff --git a/gst/rtsp-server/rtsp-params.c b/gst/rtsp-server/rtsp-params.c new file mode 100644 index 0000000..6025722 --- /dev/null +++ b/gst/rtsp-server/rtsp-params.c @@ -0,0 +1,77 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-params + * @short_description: Param get and set implementation + * @see_also: #GstRTSPClient + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include + +#include "rtsp-params.h" + +/** + * gst_rtsp_params_set: + * @client: a #GstRTSPClient + * @ctx: (transfer none): a #GstRTSPContext + * + * Set parameters (not implemented yet) + * + * Returns: a #GstRTSPResult + */ +GstRTSPResult +gst_rtsp_params_set (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPStatusCode code; + + /* FIXME, actually parse the request based on the mime type and try to repond + * with a list of the parameters */ + code = GST_RTSP_STS_PARAMETER_NOT_UNDERSTOOD; + + gst_rtsp_message_init_response (ctx->response, code, + gst_rtsp_status_as_text (code), ctx->request); + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_params_get: + * @client: a #GstRTSPClient + * @ctx: (transfer none): a #GstRTSPContext + * + * Get parameters (not implemented yet) + * + * Returns: a #GstRTSPResult + */ +GstRTSPResult +gst_rtsp_params_get (GstRTSPClient * client, GstRTSPContext * ctx) +{ + GstRTSPStatusCode code; + + /* FIXME, actually parse the request based on the mime type and try to repond + * with a list of the parameters */ + code = GST_RTSP_STS_PARAMETER_NOT_UNDERSTOOD; + + gst_rtsp_message_init_response (ctx->response, code, + gst_rtsp_status_as_text (code), ctx->request); + + return GST_RTSP_OK; +} diff --git a/gst/rtsp-server/rtsp-params.h b/gst/rtsp-server/rtsp-params.h new file mode 100644 index 0000000..563757d --- /dev/null +++ b/gst/rtsp-server/rtsp-params.h @@ -0,0 +1,38 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include +#include + +#ifndef __GST_RTSP_PARAMS_H__ +#define __GST_RTSP_PARAMS_H__ + +#include "rtsp-client.h" +#include "rtsp-session.h" + +G_BEGIN_DECLS + +GstRTSPResult gst_rtsp_params_set (GstRTSPClient * client, GstRTSPContext * ctx); +GstRTSPResult gst_rtsp_params_get (GstRTSPClient * client, GstRTSPContext * ctx); + +G_END_DECLS + +#endif /* __GST_RTSP_PARAMS_H__ */ diff --git a/gst/rtsp-server/rtsp-permissions.c b/gst/rtsp-server/rtsp-permissions.c new file mode 100644 index 0000000..66e9e44 --- /dev/null +++ b/gst/rtsp-server/rtsp-permissions.c @@ -0,0 +1,276 @@ +/* GStreamer + * Copyright (C) 2013 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-permissions + * @short_description: Roles and associated permissions + * @see_also: #GstRTSPToken, #GstRTSPAuth + * + * The #GstRTSPPermissions object contains an array of roles and associated + * permissions. The roles are represented with a string and the permissions with + * a generic #GstStructure. + * + * The permissions are deliberately kept generic. The possible values of the + * roles and #GstStructure keys and values are only determined by the #GstRTSPAuth + * object that performs the checks on the permissions and the current + * #GstRTSPToken. + * + * As a convenience function, gst_rtsp_permissions_is_allowed() can be used to + * check if the permissions contains a role that contains the boolean value + * %TRUE for the the given key. + * + * Last reviewed on 2013-07-15 (1.0.0) + */ + +#include + +#include "rtsp-permissions.h" + +typedef struct _GstRTSPPermissionsImpl +{ + GstRTSPPermissions permissions; + + /* Roles, array of GstStructure */ + GPtrArray *roles; +} GstRTSPPermissionsImpl; + +static void +free_structure (GstStructure * structure) +{ + gst_structure_set_parent_refcount (structure, NULL); + gst_structure_free (structure); +} + +//GST_DEBUG_CATEGORY_STATIC (rtsp_permissions_debug); +//#define GST_CAT_DEFAULT rtsp_permissions_debug + +GST_DEFINE_MINI_OBJECT_TYPE (GstRTSPPermissions, gst_rtsp_permissions); + +static void gst_rtsp_permissions_init (GstRTSPPermissionsImpl * permissions); + +static void +_gst_rtsp_permissions_free (GstRTSPPermissions * permissions) +{ + GstRTSPPermissionsImpl *impl = (GstRTSPPermissionsImpl *) permissions; + + g_ptr_array_free (impl->roles, TRUE); + + g_slice_free1 (sizeof (GstRTSPPermissionsImpl), permissions); +} + +static GstRTSPPermissions * +_gst_rtsp_permissions_copy (GstRTSPPermissionsImpl * permissions) +{ + GstRTSPPermissionsImpl *copy; + guint i; + + copy = (GstRTSPPermissionsImpl *) gst_rtsp_permissions_new (); + + for (i = 0; i < permissions->roles->len; i++) { + GstStructure *entry = g_ptr_array_index (permissions->roles, i); + GstStructure *entry_copy = gst_structure_copy (entry); + + gst_structure_set_parent_refcount (entry_copy, + ©->permissions.mini_object.refcount); + g_ptr_array_add (copy->roles, entry_copy); + } + + return GST_RTSP_PERMISSIONS (copy); +} + +static void +gst_rtsp_permissions_init (GstRTSPPermissionsImpl * permissions) +{ + gst_mini_object_init (GST_MINI_OBJECT_CAST (permissions), 0, + GST_TYPE_RTSP_PERMISSIONS, + (GstMiniObjectCopyFunction) _gst_rtsp_permissions_copy, NULL, + (GstMiniObjectFreeFunction) _gst_rtsp_permissions_free); + + permissions->roles = + g_ptr_array_new_with_free_func ((GDestroyNotify) free_structure); +} + +/** + * gst_rtsp_permissions_new: + * + * Create a new empty Authorization permissions. + * + * Returns: (transfer full): a new empty authorization permissions. + */ +GstRTSPPermissions * +gst_rtsp_permissions_new (void) +{ + GstRTSPPermissionsImpl *permissions; + + permissions = g_slice_new0 (GstRTSPPermissionsImpl); + gst_rtsp_permissions_init (permissions); + + return GST_RTSP_PERMISSIONS (permissions); +} + +/** + * gst_rtsp_permissions_add_role: + * @permissions: a #GstRTSPPermissions + * @role: a role + * @fieldname: the first field name + * @...: additional arguments + * + * Add a new @role to @permissions with the given variables. The fields + * are the same layout as gst_structure_new(). + */ +void +gst_rtsp_permissions_add_role (GstRTSPPermissions * permissions, + const gchar * role, const gchar * fieldname, ...) +{ + va_list var_args; + + va_start (var_args, fieldname); + gst_rtsp_permissions_add_role_valist (permissions, role, fieldname, var_args); + va_end (var_args); +} + +/** + * gst_rtsp_permissions_add_role_valist: + * @permissions: a #GstRTSPPermissions + * @role: a role + * @fieldname: the first field name + * @var_args: additional fields to add + * + * Add a new @role to @permissions with the given variables. Structure fields + * are set according to the varargs in a manner similar to gst_structure_new(). + */ +void +gst_rtsp_permissions_add_role_valist (GstRTSPPermissions * permissions, + const gchar * role, const gchar * fieldname, va_list var_args) +{ + GstRTSPPermissionsImpl *impl = (GstRTSPPermissionsImpl *) permissions; + GstStructure *structure; + guint i, len; + + g_return_if_fail (GST_IS_RTSP_PERMISSIONS (permissions)); + g_return_if_fail (gst_mini_object_is_writable (&permissions->mini_object)); + g_return_if_fail (role != NULL); + g_return_if_fail (fieldname != NULL); + + structure = gst_structure_new_valist (role, fieldname, var_args); + g_return_if_fail (structure != NULL); + + len = impl->roles->len; + for (i = 0; i < len; i++) { + GstStructure *entry = g_ptr_array_index (impl->roles, i); + + if (gst_structure_has_name (entry, role)) { + g_ptr_array_remove_index_fast (impl->roles, i); + break; + } + } + + gst_structure_set_parent_refcount (structure, + &impl->permissions.mini_object.refcount); + g_ptr_array_add (impl->roles, structure); +} + +/** + * gst_rtsp_permissions_remove_role: + * @permissions: a #GstRTSPPermissions + * @role: a role + * + * Remove all permissions for @role in @permissions. + */ +void +gst_rtsp_permissions_remove_role (GstRTSPPermissions * permissions, + const gchar * role) +{ + GstRTSPPermissionsImpl *impl = (GstRTSPPermissionsImpl *) permissions; + guint i, len; + + g_return_if_fail (GST_IS_RTSP_PERMISSIONS (permissions)); + g_return_if_fail (gst_mini_object_is_writable (&permissions->mini_object)); + g_return_if_fail (role != NULL); + + len = impl->roles->len; + for (i = 0; i < len; i++) { + GstStructure *entry = g_ptr_array_index (impl->roles, i); + + if (gst_structure_has_name (entry, role)) { + g_ptr_array_remove_index_fast (impl->roles, i); + break; + } + } +} + +/** + * gst_rtsp_permissions_get_role: + * @permissions: a #GstRTSPPermissions + * @role: a role + * + * Get all permissions for @role in @permissions. + * + * Returns: (transfer none): the structure with permissions for @role. It + * remains valid for as long as @permissions is valid. + */ +const GstStructure * +gst_rtsp_permissions_get_role (GstRTSPPermissions * permissions, + const gchar * role) +{ + GstRTSPPermissionsImpl *impl = (GstRTSPPermissionsImpl *) permissions; + guint i, len; + + g_return_val_if_fail (GST_IS_RTSP_PERMISSIONS (permissions), NULL); + g_return_val_if_fail (role != NULL, NULL); + + len = impl->roles->len; + for (i = 0; i < len; i++) { + GstStructure *entry = g_ptr_array_index (impl->roles, i); + + if (gst_structure_has_name (entry, role)) + return entry; + } + return NULL; +} + +/** + * gst_rtsp_permissions_is_allowed: + * @permissions: a #GstRTSPPermissions + * @role: a role + * @permission: a permission + * + * Check if @role in @permissions is given permission for @permission. + * + * Returns: %TRUE if @role is allowed @permission. + */ +gboolean +gst_rtsp_permissions_is_allowed (GstRTSPPermissions * permissions, + const gchar * role, const gchar * permission) +{ + const GstStructure *str; + gboolean result; + + g_return_val_if_fail (GST_IS_RTSP_PERMISSIONS (permissions), FALSE); + g_return_val_if_fail (role != NULL, FALSE); + g_return_val_if_fail (permission != NULL, FALSE); + + str = gst_rtsp_permissions_get_role (permissions, role); + if (str == NULL) + return FALSE; + + if (!gst_structure_get_boolean (str, permission, &result)) + result = FALSE; + + return result; +} diff --git a/gst/rtsp-server/rtsp-permissions.h b/gst/rtsp-server/rtsp-permissions.h new file mode 100644 index 0000000..9e739c7 --- /dev/null +++ b/gst/rtsp-server/rtsp-permissions.h @@ -0,0 +1,101 @@ +/* GStreamer + * Copyright (C) 2010 Wim Taymans + * + * 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. + */ + +#include + +#ifndef __GST_RTSP_PERMISSIONS_H__ +#define __GST_RTSP_PERMISSIONS_H__ + +typedef struct _GstRTSPPermissions GstRTSPPermissions; + +G_BEGIN_DECLS + +GType gst_rtsp_permissions_get_type (void); + +#define GST_TYPE_RTSP_PERMISSIONS (gst_rtsp_permissions_get_type ()) +#define GST_IS_RTSP_PERMISSIONS(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_RTSP_PERMISSIONS)) +#define GST_RTSP_PERMISSIONS_CAST(obj) ((GstRTSPPermissions*)(obj)) +#define GST_RTSP_PERMISSIONS(obj) (GST_RTSP_PERMISSIONS_CAST(obj)) + +/** + * GstRTSPPermissions: + * + * The opaque permissions structure. It is used to define the permissions + * of objects in different roles. + */ +struct _GstRTSPPermissions { + GstMiniObject mini_object; +}; + +/* refcounting */ +/** + * gst_rtsp_permissions_ref: + * @permissions: The permissions to refcount + * + * Increase the refcount of this permissions. + * + * Returns: (transfer full): @permissions (for convenience when doing assignments) + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC GstRTSPPermissions * gst_rtsp_permissions_ref (GstRTSPPermissions * permissions); +#endif + +static inline GstRTSPPermissions * +gst_rtsp_permissions_ref (GstRTSPPermissions * permissions) +{ + return (GstRTSPPermissions *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (permissions)); +} + +/** + * gst_rtsp_permissions_unref: + * @permissions: (transfer full): the permissions to refcount + * + * Decrease the refcount of an permissions, freeing it if the refcount reaches 0. + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC void gst_rtsp_permissions_unref (GstRTSPPermissions * permissions); +#endif + +static inline void +gst_rtsp_permissions_unref (GstRTSPPermissions * permissions) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (permissions)); +} + + +GstRTSPPermissions * gst_rtsp_permissions_new (void); + +void gst_rtsp_permissions_add_role (GstRTSPPermissions *permissions, + const gchar *role, + const gchar *fieldname, ...); +void gst_rtsp_permissions_add_role_valist (GstRTSPPermissions *permissions, + const gchar *role, + const gchar *fieldname, + va_list var_args); +void gst_rtsp_permissions_remove_role (GstRTSPPermissions *permissions, + const gchar *role); +const GstStructure * gst_rtsp_permissions_get_role (GstRTSPPermissions *permissions, + const gchar *role); + +gboolean gst_rtsp_permissions_is_allowed (GstRTSPPermissions *permissions, + const gchar *role, const gchar *permission); + +G_END_DECLS + +#endif /* __GST_RTSP_PERMISSIONS_H__ */ diff --git a/gst/rtsp-server/rtsp-sdp.c b/gst/rtsp-server/rtsp-sdp.c new file mode 100644 index 0000000..07aea90 --- /dev/null +++ b/gst/rtsp-server/rtsp-sdp.c @@ -0,0 +1,482 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-sdp + * @short_description: Make SDP messages + * @see_also: #GstRTSPMedia + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include + +#include + +#include "rtsp-sdp.h" + +#define AES_128_KEY_LEN 16 +#define AES_256_KEY_LEN 32 + +#define HMAC_32_KEY_LEN 4 +#define HMAC_80_KEY_LEN 10 + +static gboolean +get_info_from_tags (GstPad * pad, GstEvent ** event, gpointer user_data) +{ + GstSDPMedia *media = (GstSDPMedia *) user_data; + + if (GST_EVENT_TYPE (*event) == GST_EVENT_TAG) { + GstTagList *tags; + guint bitrate = 0; + + gst_event_parse_tag (*event, &tags); + + if (gst_tag_list_get_scope (tags) != GST_TAG_SCOPE_STREAM) + return TRUE; + + if (!gst_tag_list_get_uint (tags, GST_TAG_MAXIMUM_BITRATE, + &bitrate) || bitrate == 0) + if (!gst_tag_list_get_uint (tags, GST_TAG_BITRATE, &bitrate) || + bitrate == 0) + return TRUE; + + /* set bandwidth (kbits/s) */ + gst_sdp_media_add_bandwidth (media, GST_SDP_BWTYPE_AS, bitrate / 1000); + + return FALSE; + + } + + return TRUE; +} + +static void +update_sdp_from_tags (GstRTSPStream * stream, GstSDPMedia * stream_media) +{ + GstPad *src_pad; + + src_pad = gst_rtsp_stream_get_srcpad (stream); + + gst_pad_sticky_events_foreach (src_pad, get_info_from_tags, stream_media); + + gst_object_unref (src_pad); +} + +static guint8 +enc_key_length_from_cipher_name (const gchar * cipher) +{ + if (g_strcmp0 (cipher, "aes-128-icm") == 0) + return AES_128_KEY_LEN; + else if (g_strcmp0 (cipher, "aes-256-icm") == 0) + return AES_256_KEY_LEN; + else { + GST_ERROR ("encryption algorithm '%s' not supported", cipher); + return 0; + } +} + +static guint8 +auth_key_length_from_auth_name (const gchar * auth) +{ + if (g_strcmp0 (auth, "hmac-sha1-32") == 0) + return HMAC_32_KEY_LEN; + else if (g_strcmp0 (auth, "hmac-sha1-80") == 0) + return HMAC_80_KEY_LEN; + else { + GST_ERROR ("authentication algorithm '%s' not supported", auth); + return 0; + } +} + +static void +make_media (GstSDPMessage * sdp, GstSDPInfo * info, GstRTSPMedia * media, + GstRTSPStream * stream, GstStructure * s, GstRTSPProfile profile) +{ + GstSDPMedia *smedia; + const gchar *caps_str, *caps_enc, *caps_params; + gchar *tmp; + gint caps_pt, caps_rate; + guint n_fields, j; + gboolean first; + GString *fmtp; + GstRTSPLowerTrans ltrans; + GSocketFamily family; + const gchar *addrtype, *proto; + gchar *address; + guint ttl; + + gst_sdp_media_new (&smedia); + + /* get media type and payload for the m= line */ + caps_str = gst_structure_get_string (s, "media"); + gst_sdp_media_set_media (smedia, caps_str); + + gst_structure_get_int (s, "payload", &caps_pt); + tmp = g_strdup_printf ("%d", caps_pt); + gst_sdp_media_add_format (smedia, tmp); + g_free (tmp); + + gst_sdp_media_set_port_info (smedia, 0, 1); + + switch (profile) { + case GST_RTSP_PROFILE_AVP: + proto = "RTP/AVP"; + break; + case GST_RTSP_PROFILE_AVPF: + proto = "RTP/AVPF"; + break; + case GST_RTSP_PROFILE_SAVP: + proto = "RTP/SAVP"; + break; + case GST_RTSP_PROFILE_SAVPF: + proto = "RTP/SAVPF"; + break; + default: + proto = "udp"; + break; + } + gst_sdp_media_set_proto (smedia, proto); + + if (info->is_ipv6) { + addrtype = "IP6"; + family = G_SOCKET_FAMILY_IPV6; + } else { + addrtype = "IP4"; + family = G_SOCKET_FAMILY_IPV4; + } + + ltrans = gst_rtsp_stream_get_protocols (stream); + if (ltrans == GST_RTSP_LOWER_TRANS_UDP_MCAST) { + GstRTSPAddress *addr; + + addr = gst_rtsp_stream_get_multicast_address (stream, family); + if (addr == NULL) + goto no_multicast; + + address = g_strdup (addr->address); + ttl = addr->ttl; + gst_rtsp_address_free (addr); + } else { + ttl = 16; + if (info->is_ipv6) + address = g_strdup ("::"); + else + address = g_strdup ("0.0.0.0"); + } + + /* for the c= line */ + gst_sdp_media_add_connection (smedia, "IN", addrtype, address, ttl, 1); + g_free (address); + + /* get clock-rate, media type and params for the rtpmap attribute */ + gst_structure_get_int (s, "clock-rate", &caps_rate); + caps_enc = gst_structure_get_string (s, "encoding-name"); + caps_params = gst_structure_get_string (s, "encoding-params"); + + if (caps_enc) { + if (caps_params) + tmp = g_strdup_printf ("%d %s/%d/%s", caps_pt, caps_enc, caps_rate, + caps_params); + else + tmp = g_strdup_printf ("%d %s/%d", caps_pt, caps_enc, caps_rate); + + gst_sdp_media_add_attribute (smedia, "rtpmap", tmp); + g_free (tmp); + } + + /* the config uri */ + tmp = gst_rtsp_stream_get_control (stream); + gst_sdp_media_add_attribute (smedia, "control", tmp); + g_free (tmp); + + + /* check for srtp */ + do { + GstBuffer *srtpkey; + const GValue *val; + const gchar *srtpcipher, *srtpauth, *srtcpcipher, *srtcpauth; + GstMIKEYMessage *msg; + GstMIKEYPayload *payload, *pkd; + GBytes *bytes; + GstMapInfo info; + const guint8 *data; + gsize size; + gchar *base64; + guint8 byte; + guint32 ssrc; + + val = gst_structure_get_value (s, "srtp-key"); + if (val == NULL) + break; + + srtpkey = gst_value_get_buffer (val); + if (srtpkey == NULL) + break; + + srtpcipher = gst_structure_get_string (s, "srtp-cipher"); + srtpauth = gst_structure_get_string (s, "srtp-auth"); + srtcpcipher = gst_structure_get_string (s, "srtcp-cipher"); + srtcpauth = gst_structure_get_string (s, "srtcp-auth"); + + if (srtpcipher == NULL || srtpauth == NULL || srtcpcipher == NULL || + srtcpauth == NULL) + break; + + msg = gst_mikey_message_new (); + /* unencrypted MIKEY message, we send this over TLS so this is allowed */ + gst_mikey_message_set_info (msg, GST_MIKEY_VERSION, GST_MIKEY_TYPE_PSK_INIT, + FALSE, GST_MIKEY_PRF_MIKEY_1, 0, GST_MIKEY_MAP_TYPE_SRTP); + /* add policy '0' for our SSRC */ + gst_rtsp_stream_get_ssrc (stream, &ssrc); + gst_mikey_message_add_cs_srtp (msg, 0, ssrc, 0); + /* timestamp is now */ + gst_mikey_message_add_t_now_ntp_utc (msg); + /* add some random data */ + gst_mikey_message_add_rand_len (msg, 16); + + /* the policy '0' is SRTP with the above discovered algorithms */ + payload = gst_mikey_payload_new (GST_MIKEY_PT_SP); + gst_mikey_payload_sp_set (payload, 0, GST_MIKEY_SEC_PROTO_SRTP); + + /* only AES-CM is supported */ + byte = 1; + gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_ENC_ALG, 1, + &byte); + /* Encryption key length */ + byte = enc_key_length_from_cipher_name (srtpcipher); + gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_ENC_KEY_LEN, 1, + &byte); + /* only HMAC-SHA1 */ + gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_AUTH_ALG, 1, + &byte); + /* Authentication key length */ + byte = auth_key_length_from_auth_name (srtpauth); + gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_AUTH_KEY_LEN, 1, + &byte); + /* we enable encryption on RTP and RTCP */ + gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_SRTP_ENC, 1, + &byte); + gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_SRTCP_ENC, 1, + &byte); + /* we enable authentication on RTP and RTCP */ + gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_SRTP_AUTH, 1, + &byte); + gst_mikey_message_add_payload (msg, payload); + + /* make unencrypted KEMAC */ + payload = gst_mikey_payload_new (GST_MIKEY_PT_KEMAC); + gst_mikey_payload_kemac_set (payload, GST_MIKEY_ENC_NULL, + GST_MIKEY_MAC_NULL); + + /* add the key in key data */ + pkd = gst_mikey_payload_new (GST_MIKEY_PT_KEY_DATA); + gst_buffer_map (srtpkey, &info, GST_MAP_READ); + gst_mikey_payload_key_data_set_key (pkd, GST_MIKEY_KD_TEK, info.size, + info.data); + gst_buffer_unmap (srtpkey, &info); + /* add key data to KEMAC */ + gst_mikey_payload_kemac_add_sub (payload, pkd); + gst_mikey_message_add_payload (msg, payload); + + /* now serialize this to bytes */ + bytes = gst_mikey_message_to_bytes (msg, NULL, NULL); + gst_mikey_message_unref (msg); + /* and make it into base64 */ + data = g_bytes_get_data (bytes, &size); + base64 = g_base64_encode (data, size); + g_bytes_unref (bytes); + + tmp = g_strdup_printf ("mikey %s", base64); + g_free (base64); + + gst_sdp_media_add_attribute (smedia, "key-mgmt", tmp); + g_free (tmp); + } while (FALSE); + + /* collect all other properties and add them to fmtp or attributes */ + fmtp = g_string_new (""); + g_string_append_printf (fmtp, "%d ", caps_pt); + first = TRUE; + n_fields = gst_structure_n_fields (s); + for (j = 0; j < n_fields; j++) { + const gchar *fname, *fval; + + fname = gst_structure_nth_field_name (s, j); + + /* filter out standard properties */ + if (!strcmp (fname, "media")) + continue; + if (!strcmp (fname, "payload")) + continue; + if (!strcmp (fname, "clock-rate")) + continue; + if (!strcmp (fname, "encoding-name")) + continue; + if (!strcmp (fname, "encoding-params")) + continue; + if (!strcmp (fname, "ssrc")) + continue; + if (!strcmp (fname, "clock-base")) + continue; + if (!strcmp (fname, "seqnum-base")) + continue; + if (g_str_has_prefix (fname, "srtp-")) + continue; + if (g_str_has_prefix (fname, "srtcp-")) + continue; + + if (g_str_has_prefix (fname, "a-")) { + /* attribute */ + if ((fval = gst_structure_get_string (s, fname))) + gst_sdp_media_add_attribute (smedia, fname + 2, fval); + continue; + } + if (g_str_has_prefix (fname, "x-")) { + /* attribute */ + if ((fval = gst_structure_get_string (s, fname))) + gst_sdp_media_add_attribute (smedia, fname, fval); + continue; + } + + if ((fval = gst_structure_get_string (s, fname))) { + g_string_append_printf (fmtp, "%s%s=%s", first ? "" : ";", fname, fval); + first = FALSE; + } + } + if (!first) { + tmp = g_string_free (fmtp, FALSE); + gst_sdp_media_add_attribute (smedia, "fmtp", tmp); + g_free (tmp); + } else { + g_string_free (fmtp, TRUE); + } + + update_sdp_from_tags (stream, smedia); + + gst_sdp_message_add_media (sdp, smedia); + gst_sdp_media_free (smedia); + + return; + + /* ERRORS */ +no_multicast: + { + gst_sdp_media_free (smedia); + g_warning ("ignoring stream %d without multicast address", + gst_rtsp_stream_get_index (stream)); + return; + } +} + +/** + * gst_rtsp_sdp_from_media: + * @sdp: a #GstSDPMessage + * @info: (transfer none): a #GstSDPInfo + * @media: (transfer none): a #GstRTSPMedia + * + * Add @media specific info to @sdp. @info is used to configure the connection + * information in the SDP. + * + * Returns: TRUE on success. + */ +gboolean +gst_rtsp_sdp_from_media (GstSDPMessage * sdp, GstSDPInfo * info, + GstRTSPMedia * media) +{ + guint i, n_streams; + gchar *rangestr; + + n_streams = gst_rtsp_media_n_streams (media); + + rangestr = gst_rtsp_media_get_range_string (media, FALSE, GST_RTSP_RANGE_NPT); + if (rangestr == NULL) + goto not_prepared; + + gst_sdp_message_add_attribute (sdp, "range", rangestr); + g_free (rangestr); + + for (i = 0; i < n_streams; i++) { + GstRTSPStream *stream; + GstCaps *caps; + GstStructure *s; + GstRTSPProfile profiles; + guint mask; + + stream = gst_rtsp_media_get_stream (media, i); + caps = gst_rtsp_stream_get_caps (stream); + + if (caps == NULL) { + g_warning ("ignoring stream %d without media type", i); + continue; + } + + s = gst_caps_get_structure (caps, 0); + if (s == NULL) { + gst_caps_unref (caps); + g_warning ("ignoring stream %d without media type", i); + continue; + } + + /* make a new media for each profile */ + profiles = gst_rtsp_stream_get_profiles (stream); + mask = 1; + while (profiles >= mask) { + GstRTSPProfile prof = profiles & mask; + + if (prof) + make_media (sdp, info, media, stream, s, prof); + + mask <<= 1; + } + gst_caps_unref (caps); + } + + { + GstNetTimeProvider *provider; + + if ((provider = + gst_rtsp_media_get_time_provider (media, info->server_ip, 0))) { + GstClock *clock; + gchar *address, *str; + gint port; + + g_object_get (provider, "clock", &clock, "address", &address, "port", + &port, NULL); + + str = g_strdup_printf ("GstNetTimeProvider %s %s:%d %" G_GUINT64_FORMAT, + g_type_name (G_TYPE_FROM_INSTANCE (clock)), address, port, + gst_clock_get_time (clock)); + + gst_sdp_message_add_attribute (sdp, "x-gst-clock", str); + g_free (str); + gst_object_unref (clock); + g_free (address); + gst_object_unref (provider); + } + } + + return TRUE; + + /* ERRORS */ +not_prepared: + { + GST_ERROR ("media %p is not prepared", media); + return FALSE; + } +} diff --git a/gst/rtsp-server/rtsp-sdp.h b/gst/rtsp-server/rtsp-sdp.h new file mode 100644 index 0000000..7732f36 --- /dev/null +++ b/gst/rtsp-server/rtsp-sdp.h @@ -0,0 +1,40 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include +#include + +#include "rtsp-media.h" + +#ifndef __GST_RTSP_SDP_H__ +#define __GST_RTSP_SDP_H__ + +G_BEGIN_DECLS + +typedef struct { + gboolean is_ipv6; + const gchar *server_ip; +} GstSDPInfo; + +/* creating SDP */ +gboolean gst_rtsp_sdp_from_media (GstSDPMessage *sdp, GstSDPInfo *info, GstRTSPMedia * media); + +G_END_DECLS + +#endif /* __GST_RTSP_SDP_H__ */ diff --git a/gst/rtsp-server/rtsp-server-wfd.c b/gst/rtsp-server/rtsp-server-wfd.c new file mode 100644 index 0000000..15dac76 --- /dev/null +++ b/gst/rtsp-server/rtsp-server-wfd.c @@ -0,0 +1,332 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-server + * @short_description: The main server object + * @see_also: #GstRTSPClient, #GstRTSPThreadPool + * + * The server object is the object listening for connections on a port and + * creating #GstRTSPClient objects to handle those connections. + * + * The server will listen on the address set with gst_rtsp_server_set_address() + * and the port or service configured with gst_rtsp_server_set_service(). + * Use gst_rtsp_server_set_backlog() to configure the amount of pending requests + * that the server will keep. By default the server listens on the current + * network (0.0.0.0) and port 8554. + * + * The server will require an SSL connection when a TLS certificate has been + * set in the auth object with gst_rtsp_auth_set_tls_certificate(). + * + * To start the server, use gst_rtsp_server_attach() to attach it to a + * #GMainContext. For more control, gst_rtsp_server_create_source() and + * gst_rtsp_server_create_socket() can be used to get a #GSource and #GSocket + * respectively. + * + * gst_rtsp_server_transfer_connection() can be used to transfer an existing + * socket to the RTSP server, for example from an HTTP server. + * + * Once the server socket is attached to a mainloop, it will start accepting + * connections. When a new connection is received, a new #GstRTSPClient object + * is created to handle the connection. The new client will be configured with + * the server #GstRTSPAuth, #GstRTSPMountPoints, #GstRTSPSessionPool and + * #GstRTSPThreadPool. + * + * The server uses the configured #GstRTSPThreadPool object to handle the + * remainder of the communication with this client. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ +#include +#include + +#include "rtsp-server-wfd.h" +#include "rtsp-client-wfd.h" + +#define GST_RTSP_WFD_SERVER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_WFD_SERVER, GstRTSPWFDServerPrivate)) + +#define GST_RTSP_WFD_SERVER_GET_LOCK(server) (&(GST_RTSP_WFD_SERVER_CAST(server)->priv->lock)) +#define GST_RTSP_WFD_SERVER_LOCK(server) (g_mutex_lock(GST_RTSP_WFD_SERVER_GET_LOCK(server))) +#define GST_RTSP_WFD_SERVER_UNLOCK(server) (g_mutex_unlock(GST_RTSP_WFD_SERVER_GET_LOCK(server))) + +struct _GstRTSPWFDServerPrivate +{ + GMutex lock; /* protects everything in this struct */ + + /* the clients that are connected */ + GList *clients; + guint64 native_resolution; + guint64 supported_resolution; + guint8 audio_codec; +}; + +G_DEFINE_TYPE (GstRTSPWFDServer, gst_rtsp_wfd_server, GST_TYPE_RTSP_SERVER); + +GST_DEBUG_CATEGORY_STATIC (rtsp_wfd_server_debug); +#define GST_CAT_DEFAULT rtsp_wfd_server_debug + +static void gst_rtsp_wfd_server_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_wfd_server_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); +static void gst_rtsp_wfd_server_finalize (GObject * object); + +static GstRTSPClient *create_client_wfd (GstRTSPServer * server); +static void client_connected_wfd (GstRTSPServer * server, + GstRTSPClient * client); + +static void +gst_rtsp_wfd_server_class_init (GstRTSPWFDServerClass * klass) +{ + GObjectClass *gobject_class; + GstRTSPServerClass *rtsp_server_class; + + g_type_class_add_private (klass, sizeof (GstRTSPWFDServerPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + rtsp_server_class = GST_RTSP_SERVER_CLASS (klass); + + gobject_class->get_property = gst_rtsp_wfd_server_get_property; + gobject_class->set_property = gst_rtsp_wfd_server_set_property; + gobject_class->finalize = gst_rtsp_wfd_server_finalize; + + rtsp_server_class->create_client = create_client_wfd; + rtsp_server_class->client_connected = client_connected_wfd; + + + GST_DEBUG_CATEGORY_INIT (rtsp_wfd_server_debug, "rtspwfdserver", 0, + "GstRTSPWFDServer"); +} + +static void +gst_rtsp_wfd_server_init (GstRTSPWFDServer * server) +{ + GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE (server); + + g_return_if_fail (priv != NULL); + + server->priv = priv; + server->priv->native_resolution = 0; + server->priv->supported_resolution = 1; + server->priv->audio_codec = 2; + GST_INFO_OBJECT (server, "New server is initialized"); +} + +static void +gst_rtsp_wfd_server_finalize (GObject * object) +{ + GstRTSPWFDServer *server = GST_RTSP_WFD_SERVER (object); + //GstRTSPWFDServerPrivate *priv = server->priv; + + GST_DEBUG_OBJECT (server, "finalize server"); + + G_OBJECT_CLASS (gst_rtsp_wfd_server_parent_class)->finalize (object); +} + +/** + * gst_rtsp_server_new: + * + * Create a new #GstRTSPWFDServer instance. + */ +GstRTSPWFDServer * +gst_rtsp_wfd_server_new (void) +{ + GstRTSPWFDServer *result; + + result = g_object_new (GST_TYPE_RTSP_WFD_SERVER, NULL); + + return result; +} + +static void +gst_rtsp_wfd_server_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + //GstRTSPWFDServer *server = GST_RTSP_WFD_SERVER (object); + + switch (propid) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_wfd_server_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + //GstRTSPWFDServer *server = GST_RTSP_WFD_SERVER (object); + + switch (propid) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static gboolean +_start_wfd (gpointer data) +{ + GstRTSPWFDClient *client = (GstRTSPWFDClient *) data; + + GST_INFO_OBJECT (client, "WFD client is STARTing"); + + gst_rtsp_wfd_client_start_wfd (client); + return FALSE; +} + +static void +client_connected_wfd (GstRTSPServer * server, GstRTSPClient * client) +{ + GST_INFO_OBJECT (server, "Client is connected"); + + gst_rtsp_wfd_client_set_host_address (GST_RTSP_WFD_CLIENT_CAST (client), + gst_rtsp_server_get_address (server)); + g_idle_add (_start_wfd, client); + return; +} + +static GstRTSPClient * +create_client_wfd (GstRTSPServer * server) +{ + GstRTSPWFDClient *client; + GstRTSPThreadPool *thread_pool = NULL; + GstRTSPSessionPool *session_pool = NULL; + GstRTSPMountPoints *mount_points = NULL; + GstRTSPAuth *auth = NULL; + GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE(server); + + g_return_val_if_fail (priv != NULL, NULL); + + GST_INFO_OBJECT (server, "New Client is being created"); + + /* a new client connected, create a session to handle the client. */ + client = gst_rtsp_wfd_client_new (); + + thread_pool = gst_rtsp_server_get_thread_pool (server); + session_pool = gst_rtsp_server_get_session_pool (server); + mount_points = gst_rtsp_server_get_mount_points (server); + auth = gst_rtsp_server_get_auth (server); + + /* set the session pool that this client should use */ + GST_RTSP_WFD_SERVER_LOCK (server); + gst_rtsp_client_set_session_pool (GST_RTSP_CLIENT_CAST (client), + session_pool); + /* set the mount points that this client should use */ + gst_rtsp_client_set_mount_points (GST_RTSP_CLIENT_CAST (client), + mount_points); + /* set authentication manager */ + gst_rtsp_client_set_auth (GST_RTSP_CLIENT_CAST (client), auth); + /* set threadpool */ + gst_rtsp_client_set_thread_pool (GST_RTSP_CLIENT_CAST (client), thread_pool); + + gst_rtsp_wfd_client_set_video_supported_resolution (client, + priv->supported_resolution); + + gst_rtsp_wfd_client_set_video_native_resolution (client, + priv->native_resolution); + + gst_rtsp_wfd_client_set_audio_codec (client, + priv->audio_codec); + + GST_RTSP_WFD_SERVER_UNLOCK (server); + + return GST_RTSP_CLIENT (client); +} + +GstRTSPResult +gst_rtsp_wfd_server_trigger_request (GstRTSPServer * server, + GstWFDTriggerType type) +{ + GstRTSPResult res = GST_RTSP_OK; + GList *clients, *walk, *next; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), GST_RTSP_ERROR); + + clients = gst_rtsp_server_client_filter (server, NULL, NULL); + if (clients == NULL) { + GST_ERROR_OBJECT (server, "There is no client in this server"); + } + + for (walk = clients; walk; walk = next) { + GstRTSPClient *client = walk->data; + + next = g_list_next (walk); + + res = + gst_rtsp_wfd_client_trigger_request (GST_RTSP_WFD_CLIENT (client), + type); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (server, "Failed to send trigger request %d", type); + } + g_object_unref (client); + } + + return res; + +} + +GstRTSPResult +gst_rtsp_wfd_server_set_supported_reso(GstRTSPWFDServer *server, guint64 supported_reso) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE(server); + + g_return_val_if_fail (GST_IS_RTSP_WFD_SERVER (server), GST_RTSP_ERROR); + g_return_val_if_fail (priv != NULL, GST_RTSP_ERROR); + + GST_RTSP_WFD_SERVER_LOCK (server); + + priv->supported_resolution = supported_reso; + + GST_RTSP_WFD_SERVER_UNLOCK (server); + return res; +} + +GstRTSPResult +gst_rtsp_wfd_server_set_video_native_reso (GstRTSPWFDServer *server, guint64 native_reso) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE(server); + + g_return_val_if_fail (GST_IS_RTSP_WFD_SERVER (server), GST_RTSP_ERROR); + g_return_val_if_fail (priv != NULL, GST_RTSP_ERROR); + + GST_RTSP_WFD_SERVER_LOCK (server); + + priv->native_resolution = native_reso; + + GST_RTSP_WFD_SERVER_UNLOCK (server); + return res; +} + +GstRTSPResult +gst_rtsp_wfd_server_set_audio_codec (GstRTSPWFDServer *server, guint8 audio_codec) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE(server); + + g_return_val_if_fail (GST_IS_RTSP_WFD_SERVER (server), GST_RTSP_ERROR); + g_return_val_if_fail (priv != NULL, GST_RTSP_ERROR); + + GST_RTSP_WFD_SERVER_LOCK (server); + + priv->audio_codec = audio_codec; + + GST_RTSP_WFD_SERVER_UNLOCK (server); + return res; +} diff --git a/gst/rtsp-server/rtsp-server-wfd.h b/gst/rtsp-server/rtsp-server-wfd.h new file mode 100644 index 0000000..13a5f3a --- /dev/null +++ b/gst/rtsp-server/rtsp-server-wfd.h @@ -0,0 +1,155 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#ifndef __GST_RTSP_SERVER_WFD_H__ +#define __GST_RTSP_SERVER_WFD_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GstRTSPWFDServer GstRTSPWFDServer; +typedef struct _GstRTSPWFDServerClass GstRTSPWFDServerClass; +typedef struct _GstRTSPWFDServerPrivate GstRTSPWFDServerPrivate; + +#include "rtsp-session-pool.h" +#include "rtsp-mount-points.h" +#include "rtsp-server.h" +#include "rtsp-client-wfd.h" +#include "rtsp-auth.h" + +#define GST_TYPE_RTSP_WFD_SERVER (gst_rtsp_wfd_server_get_type ()) +#define GST_IS_RTSP_WFD_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_WFD_SERVER)) +#define GST_IS_RTSP_WFD_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_WFD_SERVER)) +#define GST_RTSP_WFD_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_WFD_SERVER, GstRTSPWFDServerClass)) +#define GST_RTSP_WFD_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_WFD_SERVER, GstRTSPWFDServer)) +#define GST_RTSP_WFD_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_WFD_SERVER, GstRTSPWFDServerClass)) +#define GST_RTSP_WFD_SERVER_CAST(obj) ((GstRTSPWFDServer*)(obj)) +#define GST_RTSP_WFD_SERVER_CLASS_CAST(klass) ((GstRTSPWFDServerClass*)(klass)) + +/** + * GstRTSPWFDServer: + * + * This object listens on a port, creates and manages the clients connected to + * it. + */ +struct _GstRTSPWFDServer { + GstRTSPServer parent; + + /*< private >*/ + GstRTSPWFDServerPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPServerClass: + * @create_client: Create, configure a new GstRTSPClient + * object that handles the new connection on @socket. The default + * implementation will create a GstRTSPClient and will configure the + * mount-points, auth, session-pool and thread-pool on the client. + * @client_connected: emited when a new client connected. + * + * The RTSP server class structure + */ +struct _GstRTSPWFDServerClass { + GstRTSPServerClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +GType gst_rtsp_wfd_server_get_type (void); +GstRTSPWFDServer * gst_rtsp_wfd_server_new (void); +GstRTSPResult gst_rtsp_wfd_server_trigger_request (GstRTSPServer *server, GstWFDTriggerType type); + +GstRTSPResult gst_rtsp_wfd_server_set_supported_reso (GstRTSPWFDServer *server, guint64 supported_reso); +GstRTSPResult gst_rtsp_wfd_server_set_video_native_reso (GstRTSPWFDServer *server, guint64 native_reso); +GstRTSPResult gst_rtsp_wfd_server_set_audio_codec (GstRTSPWFDServer *server, guint8 audio_codec); + +#if 0 +void gst_rtsp_server_set_address (GstRTSPServer *server, const gchar *address); +gchar * gst_rtsp_server_get_address (GstRTSPServer *server); + +void gst_rtsp_server_set_service (GstRTSPServer *server, const gchar *service); +gchar * gst_rtsp_server_get_service (GstRTSPServer *server); + +void gst_rtsp_server_set_backlog (GstRTSPServer *server, gint backlog); +gint gst_rtsp_server_get_backlog (GstRTSPServer *server); + +int gst_rtsp_server_get_bound_port (GstRTSPServer *server); + +void gst_rtsp_server_set_session_pool (GstRTSPServer *server, GstRTSPSessionPool *pool); +GstRTSPSessionPool * gst_rtsp_server_get_session_pool (GstRTSPServer *server); + +void gst_rtsp_server_set_mount_points (GstRTSPServer *server, GstRTSPMountPoints *mounts); +GstRTSPMountPoints * gst_rtsp_server_get_mount_points (GstRTSPServer *server); + +void gst_rtsp_server_set_auth (GstRTSPServer *server, GstRTSPAuth *auth); +GstRTSPAuth * gst_rtsp_server_get_auth (GstRTSPServer *server); + +void gst_rtsp_server_set_thread_pool (GstRTSPServer *server, GstRTSPThreadPool *pool); +GstRTSPThreadPool * gst_rtsp_server_get_thread_pool (GstRTSPServer *server); + +gboolean gst_rtsp_server_transfer_connection (GstRTSPServer * server, GSocket *socket, + const gchar * ip, gint port, + const gchar *initial_buffer); + +gboolean gst_rtsp_server_io_func (GSocket *socket, GIOCondition condition, + GstRTSPServer *server); + +GSocket * gst_rtsp_server_create_socket (GstRTSPServer *server, + GCancellable *cancellable, + GError **error); +GSource * gst_rtsp_server_create_source (GstRTSPServer *server, + GCancellable * cancellable, + GError **error); +guint gst_rtsp_server_attach (GstRTSPServer *server, + GMainContext *context); +/** + * GstRTSPServerClientFilterFunc: + * @server: a #GstRTSPServer object + * @client: a #GstRTSPClient in @server + * @user_data: user data that has been given to gst_rtsp_server_client_filter() + * + * This function will be called by the gst_rtsp_server_client_filter(). An + * implementation should return a value of #GstRTSPFilterResult. + * + * When this function returns #GST_RTSP_FILTER_REMOVE, @client will be removed + * from @server. + * + * A return value of #GST_RTSP_FILTER_KEEP will leave @client untouched in + * @server. + * + * A value of #GST_RTSP_FILTER_REF will add @client to the result #GList of + * gst_rtsp_server_client_filter(). + * + * Returns: a #GstRTSPFilterResult. + */ +typedef GstRTSPFilterResult (*GstRTSPServerClientFilterFunc) (GstRTSPServer *server, + GstRTSPClient *client, + gpointer user_data); + +GList * gst_rtsp_server_client_filter (GstRTSPServer *server, + GstRTSPServerClientFilterFunc func, + gpointer user_data); +#endif + +G_END_DECLS + +#endif /* __GST_RTSP_SERVER_WFD_H__ */ diff --git a/gst/rtsp-server/rtsp-server.c b/gst/rtsp-server/rtsp-server.c new file mode 100644 index 0000000..686ba03 --- /dev/null +++ b/gst/rtsp-server/rtsp-server.c @@ -0,0 +1,1430 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-server + * @short_description: The main server object + * @see_also: #GstRTSPClient, #GstRTSPThreadPool + * + * The server object is the object listening for connections on a port and + * creating #GstRTSPClient objects to handle those connections. + * + * The server will listen on the address set with gst_rtsp_server_set_address() + * and the port or service configured with gst_rtsp_server_set_service(). + * Use gst_rtsp_server_set_backlog() to configure the amount of pending requests + * that the server will keep. By default the server listens on the current + * network (0.0.0.0) and port 8554. + * + * The server will require an SSL connection when a TLS certificate has been + * set in the auth object with gst_rtsp_auth_set_tls_certificate(). + * + * To start the server, use gst_rtsp_server_attach() to attach it to a + * #GMainContext. For more control, gst_rtsp_server_create_source() and + * gst_rtsp_server_create_socket() can be used to get a #GSource and #GSocket + * respectively. + * + * gst_rtsp_server_transfer_connection() can be used to transfer an existing + * socket to the RTSP server, for example from an HTTP server. + * + * Once the server socket is attached to a mainloop, it will start accepting + * connections. When a new connection is received, a new #GstRTSPClient object + * is created to handle the connection. The new client will be configured with + * the server #GstRTSPAuth, #GstRTSPMountPoints, #GstRTSPSessionPool and + * #GstRTSPThreadPool. + * + * The server uses the configured #GstRTSPThreadPool object to handle the + * remainder of the communication with this client. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ +#include +#include + +#include "rtsp-server.h" +#include "rtsp-client.h" + +#define GST_RTSP_SERVER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SERVER, GstRTSPServerPrivate)) + +#define GST_RTSP_SERVER_GET_LOCK(server) (&(GST_RTSP_SERVER_CAST(server)->priv->lock)) +#define GST_RTSP_SERVER_LOCK(server) (g_mutex_lock(GST_RTSP_SERVER_GET_LOCK(server))) +#define GST_RTSP_SERVER_UNLOCK(server) (g_mutex_unlock(GST_RTSP_SERVER_GET_LOCK(server))) + +struct _GstRTSPServerPrivate +{ + GMutex lock; /* protects everything in this struct */ + + /* server information */ + gchar *address; + gchar *service; + gint backlog; + + GSocket *socket; + + /* sessions on this server */ + GstRTSPSessionPool *session_pool; + + /* mount points for this server */ + GstRTSPMountPoints *mount_points; + + /* authentication manager */ + GstRTSPAuth *auth; + + /* resource manager */ + GstRTSPThreadPool *thread_pool; + + /* the clients that are connected */ + GList *clients; + guint clients_cookie; +}; + +#define DEFAULT_ADDRESS "0.0.0.0" +#define DEFAULT_BOUND_PORT -1 +/* #define DEFAULT_ADDRESS "::0" */ +#define DEFAULT_SERVICE "8554" +#define DEFAULT_BACKLOG 5 + +/* Define to use the SO_LINGER option so that the server sockets can be resused + * sooner. Disabled for now because it is not very well implemented by various + * OSes and it causes clients to fail to read the TEARDOWN response. */ +#undef USE_SOLINGER + +enum +{ + PROP_0, + PROP_ADDRESS, + PROP_SERVICE, + PROP_BOUND_PORT, + PROP_BACKLOG, + + PROP_SESSION_POOL, + PROP_MOUNT_POINTS, + PROP_LAST +}; + +enum +{ + SIGNAL_CLIENT_CONNECTED, + SIGNAL_LAST +}; + +G_DEFINE_TYPE (GstRTSPServer, gst_rtsp_server, G_TYPE_OBJECT); + +GST_DEBUG_CATEGORY_STATIC (rtsp_server_debug); +#define GST_CAT_DEFAULT rtsp_server_debug + +typedef struct _ClientContext ClientContext; + +static guint gst_rtsp_server_signals[SIGNAL_LAST] = { 0 }; + +static void gst_rtsp_server_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_server_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); +static void gst_rtsp_server_finalize (GObject * object); + +static GstRTSPClient *default_create_client (GstRTSPServer * server); + +static void +gst_rtsp_server_class_init (GstRTSPServerClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPServerPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gst_rtsp_server_get_property; + gobject_class->set_property = gst_rtsp_server_set_property; + gobject_class->finalize = gst_rtsp_server_finalize; + + /** + * GstRTSPServer::address: + * + * The address of the server. This is the address where the server will + * listen on. + */ + g_object_class_install_property (gobject_class, PROP_ADDRESS, + g_param_spec_string ("address", "Address", + "The address the server uses to listen on", DEFAULT_ADDRESS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstRTSPServer::service: + * + * The service of the server. This is either a string with the service name or + * a port number (as a string) the server will listen on. + */ + g_object_class_install_property (gobject_class, PROP_SERVICE, + g_param_spec_string ("service", "Service", + "The service or port number the server uses to listen on", + DEFAULT_SERVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstRTSPServer::bound-port: + * + * The actual port the server is listening on. Can be used to retrieve the + * port number when the server is started on port 0, which means bind to a + * random port. Set to -1 if the server has not been bound yet. + */ + g_object_class_install_property (gobject_class, PROP_BOUND_PORT, + g_param_spec_int ("bound-port", "Bound port", + "The port number the server is listening on", + -1, G_MAXUINT16, DEFAULT_BOUND_PORT, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * GstRTSPServer::backlog: + * + * The backlog argument defines the maximum length to which the queue of + * pending connections for the server may grow. If a connection request arrives + * when the queue is full, the client may receive an error with an indication of + * ECONNREFUSED or, if the underlying protocol supports retransmission, the + * request may be ignored so that a later reattempt at connection succeeds. + */ + g_object_class_install_property (gobject_class, PROP_BACKLOG, + g_param_spec_int ("backlog", "Backlog", + "The maximum length to which the queue " + "of pending connections may grow", 0, G_MAXINT, DEFAULT_BACKLOG, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstRTSPServer::session-pool: + * + * The session pool of the server. By default each server has a separate + * session pool but sessions can be shared between servers by setting the same + * session pool on multiple servers. + */ + g_object_class_install_property (gobject_class, PROP_SESSION_POOL, + g_param_spec_object ("session-pool", "Session Pool", + "The session pool to use for client session", + GST_TYPE_RTSP_SESSION_POOL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstRTSPServer::mount-points: + * + * The mount points to use for this server. By default the server has no + * mount points and thus cannot map urls to media streams. + */ + g_object_class_install_property (gobject_class, PROP_MOUNT_POINTS, + g_param_spec_object ("mount-points", "Mount Points", + "The mount points to use for client session", + GST_TYPE_RTSP_MOUNT_POINTS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_rtsp_server_signals[SIGNAL_CLIENT_CONNECTED] = + g_signal_new ("client-connected", G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPServerClass, client_connected), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_RTSP_CLIENT); + + klass->create_client = default_create_client; + + GST_DEBUG_CATEGORY_INIT (rtsp_server_debug, "rtspserver", 0, "GstRTSPServer"); +} + +static void +gst_rtsp_server_init (GstRTSPServer * server) +{ + GstRTSPServerPrivate *priv = GST_RTSP_SERVER_GET_PRIVATE (server); + + server->priv = priv; + + g_mutex_init (&priv->lock); + priv->address = g_strdup (DEFAULT_ADDRESS); + priv->service = g_strdup (DEFAULT_SERVICE); + priv->socket = NULL; + priv->backlog = DEFAULT_BACKLOG; + priv->session_pool = gst_rtsp_session_pool_new (); + priv->mount_points = gst_rtsp_mount_points_new (); + priv->thread_pool = gst_rtsp_thread_pool_new (); +} + +static void +gst_rtsp_server_finalize (GObject * object) +{ + GstRTSPServer *server = GST_RTSP_SERVER (object); + GstRTSPServerPrivate *priv = server->priv; + + GST_DEBUG_OBJECT (server, "finalize server"); + + g_free (priv->address); + g_free (priv->service); + + if (priv->socket) + g_object_unref (priv->socket); + + if (priv->session_pool) + g_object_unref (priv->session_pool); + if (priv->mount_points) + g_object_unref (priv->mount_points); + if (priv->thread_pool) + g_object_unref (priv->thread_pool); + + if (priv->auth) + g_object_unref (priv->auth); + + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (gst_rtsp_server_parent_class)->finalize (object); +} + +/** + * gst_rtsp_server_new: + * + * Create a new #GstRTSPServer instance. + * + * Returns: (transfer full): a new #GstRTSPServer + */ +GstRTSPServer * +gst_rtsp_server_new (void) +{ + GstRTSPServer *result; + + result = g_object_new (GST_TYPE_RTSP_SERVER, NULL); + + return result; +} + +/** + * gst_rtsp_server_set_address: + * @server: a #GstRTSPServer + * @address: the address + * + * Configure @server to accept connections on the given address. + * + * This function must be called before the server is bound. + */ +void +gst_rtsp_server_set_address (GstRTSPServer * server, const gchar * address) +{ + GstRTSPServerPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_SERVER (server)); + g_return_if_fail (address != NULL); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + g_free (priv->address); + priv->address = g_strdup (address); + GST_RTSP_SERVER_UNLOCK (server); +} + +/** + * gst_rtsp_server_get_address: + * @server: a #GstRTSPServer + * + * Get the address on which the server will accept connections. + * + * Returns: (transfer full): the server address. g_free() after usage. + */ +gchar * +gst_rtsp_server_get_address (GstRTSPServer * server) +{ + GstRTSPServerPrivate *priv; + gchar *result; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + result = g_strdup (priv->address); + GST_RTSP_SERVER_UNLOCK (server); + + return result; +} + +/** + * gst_rtsp_server_get_bound_port: + * @server: a #GstRTSPServer + * + * Get the port number where the server was bound to. + * + * Returns: the port number + */ +int +gst_rtsp_server_get_bound_port (GstRTSPServer * server) +{ + GstRTSPServerPrivate *priv; + GSocketAddress *address; + int result = -1; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), result); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + if (priv->socket == NULL) + goto out; + + address = g_socket_get_local_address (priv->socket, NULL); + result = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address)); + g_object_unref (address); + +out: + GST_RTSP_SERVER_UNLOCK (server); + + return result; +} + +/** + * gst_rtsp_server_set_service: + * @server: a #GstRTSPServer + * @service: the service + * + * Configure @server to accept connections on the given service. + * @service should be a string containing the service name (see services(5)) or + * a string containing a port number between 1 and 65535. + * + * When @service is set to "0", the server will listen on a random free + * port. The actual used port can be retrieved with + * gst_rtsp_server_get_bound_port(). + * + * This function must be called before the server is bound. + */ +void +gst_rtsp_server_set_service (GstRTSPServer * server, const gchar * service) +{ + GstRTSPServerPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_SERVER (server)); + g_return_if_fail (service != NULL); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + g_free (priv->service); + priv->service = g_strdup (service); + GST_RTSP_SERVER_UNLOCK (server); +} + +/** + * gst_rtsp_server_get_service: + * @server: a #GstRTSPServer + * + * Get the service on which the server will accept connections. + * + * Returns: (transfer full): the service. use g_free() after usage. + */ +gchar * +gst_rtsp_server_get_service (GstRTSPServer * server) +{ + GstRTSPServerPrivate *priv; + gchar *result; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + result = g_strdup (priv->service); + GST_RTSP_SERVER_UNLOCK (server); + + return result; +} + +/** + * gst_rtsp_server_set_backlog: + * @server: a #GstRTSPServer + * @backlog: the backlog + * + * configure the maximum amount of requests that may be queued for the + * server. + * + * This function must be called before the server is bound. + */ +void +gst_rtsp_server_set_backlog (GstRTSPServer * server, gint backlog) +{ + GstRTSPServerPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_SERVER (server)); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + priv->backlog = backlog; + GST_RTSP_SERVER_UNLOCK (server); +} + +/** + * gst_rtsp_server_get_backlog: + * @server: a #GstRTSPServer + * + * The maximum amount of queued requests for the server. + * + * Returns: the server backlog. + */ +gint +gst_rtsp_server_get_backlog (GstRTSPServer * server) +{ + GstRTSPServerPrivate *priv; + gint result; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), -1); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + result = priv->backlog; + GST_RTSP_SERVER_UNLOCK (server); + + return result; +} + +/** + * gst_rtsp_server_set_session_pool: + * @server: a #GstRTSPServer + * @pool: (transfer none): a #GstRTSPSessionPool + * + * configure @pool to be used as the session pool of @server. + */ +void +gst_rtsp_server_set_session_pool (GstRTSPServer * server, + GstRTSPSessionPool * pool) +{ + GstRTSPServerPrivate *priv; + GstRTSPSessionPool *old; + + g_return_if_fail (GST_IS_RTSP_SERVER (server)); + + priv = server->priv; + + if (pool) + g_object_ref (pool); + + GST_RTSP_SERVER_LOCK (server); + old = priv->session_pool; + priv->session_pool = pool; + GST_RTSP_SERVER_UNLOCK (server); + + if (old) + g_object_unref (old); +} + +/** + * gst_rtsp_server_get_session_pool: + * @server: a #GstRTSPServer + * + * Get the #GstRTSPSessionPool used as the session pool of @server. + * + * Returns: (transfer full): the #GstRTSPSessionPool used for sessions. g_object_unref() after + * usage. + */ +GstRTSPSessionPool * +gst_rtsp_server_get_session_pool (GstRTSPServer * server) +{ + GstRTSPServerPrivate *priv; + GstRTSPSessionPool *result; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + if ((result = priv->session_pool)) + g_object_ref (result); + GST_RTSP_SERVER_UNLOCK (server); + + return result; +} + +/** + * gst_rtsp_server_set_mount_points: + * @server: a #GstRTSPServer + * @mounts: (transfer none): a #GstRTSPMountPoints + * + * configure @mounts to be used as the mount points of @server. + */ +void +gst_rtsp_server_set_mount_points (GstRTSPServer * server, + GstRTSPMountPoints * mounts) +{ + GstRTSPServerPrivate *priv; + GstRTSPMountPoints *old; + + g_return_if_fail (GST_IS_RTSP_SERVER (server)); + + priv = server->priv; + + if (mounts) + g_object_ref (mounts); + + GST_RTSP_SERVER_LOCK (server); + old = priv->mount_points; + priv->mount_points = mounts; + GST_RTSP_SERVER_UNLOCK (server); + + if (old) + g_object_unref (old); +} + + +/** + * gst_rtsp_server_get_mount_points: + * @server: a #GstRTSPServer + * + * Get the #GstRTSPMountPoints used as the mount points of @server. + * + * Returns: (transfer full): the #GstRTSPMountPoints of @server. g_object_unref() after + * usage. + */ +GstRTSPMountPoints * +gst_rtsp_server_get_mount_points (GstRTSPServer * server) +{ + GstRTSPServerPrivate *priv; + GstRTSPMountPoints *result; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + if ((result = priv->mount_points)) + g_object_ref (result); + GST_RTSP_SERVER_UNLOCK (server); + + return result; +} + +/** + * gst_rtsp_server_set_auth: + * @server: a #GstRTSPServer + * @auth: (transfer none): a #GstRTSPAuth + * + * configure @auth to be used as the authentication manager of @server. + */ +void +gst_rtsp_server_set_auth (GstRTSPServer * server, GstRTSPAuth * auth) +{ + GstRTSPServerPrivate *priv; + GstRTSPAuth *old; + + g_return_if_fail (GST_IS_RTSP_SERVER (server)); + + priv = server->priv; + + if (auth) + g_object_ref (auth); + + GST_RTSP_SERVER_LOCK (server); + old = priv->auth; + priv->auth = auth; + GST_RTSP_SERVER_UNLOCK (server); + + if (old) + g_object_unref (old); +} + + +/** + * gst_rtsp_server_get_auth: + * @server: a #GstRTSPServer + * + * Get the #GstRTSPAuth used as the authentication manager of @server. + * + * Returns: (transfer full): the #GstRTSPAuth of @server. g_object_unref() after + * usage. + */ +GstRTSPAuth * +gst_rtsp_server_get_auth (GstRTSPServer * server) +{ + GstRTSPServerPrivate *priv; + GstRTSPAuth *result; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + if ((result = priv->auth)) + g_object_ref (result); + GST_RTSP_SERVER_UNLOCK (server); + + return result; +} + +/** + * gst_rtsp_server_set_thread_pool: + * @server: a #GstRTSPServer + * @pool: (transfer none): a #GstRTSPThreadPool + * + * configure @pool to be used as the thread pool of @server. + */ +void +gst_rtsp_server_set_thread_pool (GstRTSPServer * server, + GstRTSPThreadPool * pool) +{ + GstRTSPServerPrivate *priv; + GstRTSPThreadPool *old; + + g_return_if_fail (GST_IS_RTSP_SERVER (server)); + + priv = server->priv; + + if (pool) + g_object_ref (pool); + + GST_RTSP_SERVER_LOCK (server); + old = priv->thread_pool; + priv->thread_pool = pool; + GST_RTSP_SERVER_UNLOCK (server); + + if (old) + g_object_unref (old); +} + +/** + * gst_rtsp_server_get_thread_pool: + * @server: a #GstRTSPServer + * + * Get the #GstRTSPThreadPool used as the thread pool of @server. + * + * Returns: (transfer full): the #GstRTSPThreadPool of @server. g_object_unref() after + * usage. + */ +GstRTSPThreadPool * +gst_rtsp_server_get_thread_pool (GstRTSPServer * server) +{ + GstRTSPServerPrivate *priv; + GstRTSPThreadPool *result; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + if ((result = priv->thread_pool)) + g_object_ref (result); + GST_RTSP_SERVER_UNLOCK (server); + + return result; +} + +static void +gst_rtsp_server_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + GstRTSPServer *server = GST_RTSP_SERVER (object); + + switch (propid) { + case PROP_ADDRESS: + g_value_take_string (value, gst_rtsp_server_get_address (server)); + break; + case PROP_SERVICE: + g_value_take_string (value, gst_rtsp_server_get_service (server)); + break; + case PROP_BOUND_PORT: + g_value_set_int (value, gst_rtsp_server_get_bound_port (server)); + break; + case PROP_BACKLOG: + g_value_set_int (value, gst_rtsp_server_get_backlog (server)); + break; + case PROP_SESSION_POOL: + g_value_take_object (value, gst_rtsp_server_get_session_pool (server)); + break; + case PROP_MOUNT_POINTS: + g_value_take_object (value, gst_rtsp_server_get_mount_points (server)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_server_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + GstRTSPServer *server = GST_RTSP_SERVER (object); + + switch (propid) { + case PROP_ADDRESS: + gst_rtsp_server_set_address (server, g_value_get_string (value)); + break; + case PROP_SERVICE: + gst_rtsp_server_set_service (server, g_value_get_string (value)); + break; + case PROP_BACKLOG: + gst_rtsp_server_set_backlog (server, g_value_get_int (value)); + break; + case PROP_SESSION_POOL: + gst_rtsp_server_set_session_pool (server, g_value_get_object (value)); + break; + case PROP_MOUNT_POINTS: + gst_rtsp_server_set_mount_points (server, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +/** + * gst_rtsp_server_create_socket: + * @server: a #GstRTSPServer + * @cancellable: (allow-none): a #GCancellable + * @error: (out): a #GError + * + * Create a #GSocket for @server. The socket will listen on the + * configured service. + * + * Returns: (transfer full): the #GSocket for @server or %NULL when an error + * occurred. + */ +GSocket * +gst_rtsp_server_create_socket (GstRTSPServer * server, + GCancellable * cancellable, GError ** error) +{ + GstRTSPServerPrivate *priv; + GSocketConnectable *conn; + GSocketAddressEnumerator *enumerator; + GSocket *socket = NULL; +#ifdef USE_SOLINGER + struct linger linger; +#endif + GError *sock_error = NULL; + GError *bind_error = NULL; + guint16 port; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); + + priv = server->priv; + + GST_RTSP_SERVER_LOCK (server); + GST_DEBUG_OBJECT (server, "getting address info of %s/%s", priv->address, + priv->service); + + /* resolve the server IP address */ + port = atoi (priv->service); + if (port != 0 || !strcmp (priv->service, "0")) + conn = g_network_address_new (priv->address, port); + else + conn = g_network_service_new (priv->service, "tcp", priv->address); + + enumerator = g_socket_connectable_enumerate (conn); + g_object_unref (conn); + + /* create server socket, we loop through all the addresses until we manage to + * create a socket and bind. */ + while (TRUE) { + GSocketAddress *sockaddr; + + sockaddr = + g_socket_address_enumerator_next (enumerator, cancellable, error); + if (!sockaddr) { + if (!*error) + GST_DEBUG_OBJECT (server, "no more addresses %s", + *error ? (*error)->message : ""); + else + GST_DEBUG_OBJECT (server, "failed to retrieve next address %s", + (*error)->message); + break; + } + + /* only keep the first error */ + socket = g_socket_new (g_socket_address_get_family (sockaddr), + G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, + sock_error ? NULL : &sock_error); + + if (socket == NULL) { + GST_DEBUG_OBJECT (server, "failed to make socket (%s), try next", + sock_error->message); + g_object_unref (sockaddr); + continue; + } + + if (g_socket_bind (socket, sockaddr, TRUE, bind_error ? NULL : &bind_error)) { + /* ask what port the socket has been bound to */ + if (port == 0 || !strcmp (priv->service, "0")) { + GError *addr_error = NULL; + + g_object_unref (sockaddr); + sockaddr = g_socket_get_local_address (socket, &addr_error); + + if (addr_error != NULL) { + GST_DEBUG_OBJECT (server, + "failed to get the local address of a bound socket %s", + addr_error->message); + g_clear_error (&addr_error); + break; + } + port = + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (sockaddr)); + + if (port != 0) { + g_free (priv->service); + priv->service = g_strdup_printf ("%d", port); + } else { + GST_DEBUG_OBJECT (server, "failed to get the port of a bound socket"); + } + } + g_object_unref (sockaddr); + break; + } + + GST_DEBUG_OBJECT (server, "failed to bind socket (%s), try next", + bind_error->message); + g_object_unref (sockaddr); + g_object_unref (socket); + socket = NULL; + } + g_object_unref (enumerator); + + if (socket == NULL) + goto no_socket; + + g_clear_error (&sock_error); + g_clear_error (&bind_error); + + GST_DEBUG_OBJECT (server, "opened sending server socket"); + + /* keep connection alive; avoids SIGPIPE during write */ + g_socket_set_keepalive (socket, TRUE); + +#if 0 +#ifdef USE_SOLINGER + /* make sure socket is reset 5 seconds after close. This ensure that we can + * reuse the socket quickly while still having a chance to send data to the + * client. */ + linger.l_onoff = 1; + linger.l_linger = 5; + if (setsockopt (sockfd, SOL_SOCKET, SO_LINGER, + (void *) &linger, sizeof (linger)) < 0) + goto linger_failed; +#endif +#endif + + /* set the server socket to nonblocking */ + g_socket_set_blocking (socket, FALSE); + + /* set listen backlog */ + g_socket_set_listen_backlog (socket, priv->backlog); + + if (!g_socket_listen (socket, error)) + goto listen_failed; + + GST_DEBUG_OBJECT (server, "listening on server socket %p with queue of %d", + socket, priv->backlog); + + GST_RTSP_SERVER_UNLOCK (server); + + return socket; + + /* ERRORS */ +no_socket: + { + GST_ERROR_OBJECT (server, "failed to create socket"); + goto close_error; + } +#if 0 +#ifdef USE_SOLINGER +linger_failed: + { + GST_ERROR_OBJECT (server, "failed to no linger socket: %s", + g_strerror (errno)); + goto close_error; + } +#endif +#endif +listen_failed: + { + GST_ERROR_OBJECT (server, "failed to listen on socket: %s", + (*error)->message); + goto close_error; + } +close_error: + { + if (socket) + g_object_unref (socket); + + if (sock_error) { + if (error == NULL) + g_propagate_error (error, sock_error); + else + g_error_free (sock_error); + } + if (bind_error) { + if ((error == NULL) || (*error == NULL)) + g_propagate_error (error, bind_error); + else + g_error_free (bind_error); + } + GST_RTSP_SERVER_UNLOCK (server); + return NULL; + } +} + +struct _ClientContext +{ + GstRTSPServer *server; + GstRTSPThread *thread; + GstRTSPClient *client; +}; + +static gboolean +free_client_context (ClientContext * ctx) +{ + GST_DEBUG ("free context %p", ctx); + + GST_RTSP_SERVER_LOCK (ctx->server); + if (ctx->thread) + gst_rtsp_thread_stop (ctx->thread); + GST_RTSP_SERVER_UNLOCK (ctx->server); + + g_object_unref (ctx->client); + g_object_unref (ctx->server); + g_slice_free (ClientContext, ctx); + + return G_SOURCE_REMOVE; +} + +static void +unmanage_client (GstRTSPClient * client, ClientContext * ctx) +{ + GstRTSPServer *server = ctx->server; + GstRTSPServerPrivate *priv = server->priv; + + GST_DEBUG_OBJECT (server, "unmanage client %p", client); + + GST_RTSP_SERVER_LOCK (server); + priv->clients = g_list_remove (priv->clients, ctx); + priv->clients_cookie++; + GST_RTSP_SERVER_UNLOCK (server); + + if (ctx->thread) { + GSource *src; + + src = g_idle_source_new (); + g_source_set_callback (src, (GSourceFunc) free_client_context, ctx, NULL); + g_source_attach (src, ctx->thread->context); + g_source_unref (src); + } else { + free_client_context (ctx); + } +} + +/* add the client context to the active list of clients, takes ownership + * of client */ +static void +manage_client (GstRTSPServer * server, GstRTSPClient * client) +{ + ClientContext *cctx; + GstRTSPServerPrivate *priv = server->priv; + GMainContext *mainctx = NULL; + GstRTSPContext ctx = { NULL }; + + GST_DEBUG_OBJECT (server, "manage client %p", client); + + g_signal_emit (server, gst_rtsp_server_signals[SIGNAL_CLIENT_CONNECTED], 0, + client); + + cctx = g_slice_new0 (ClientContext); + cctx->server = g_object_ref (server); + cctx->client = client; + + GST_RTSP_SERVER_LOCK (server); + + ctx.server = server; + ctx.client = client; + + cctx->thread = gst_rtsp_thread_pool_get_thread (priv->thread_pool, + GST_RTSP_THREAD_TYPE_CLIENT, &ctx); + if (cctx->thread) + mainctx = cctx->thread->context; + else { + GSource *source; + /* find the context to add the watch */ + if ((source = g_main_current_source ())) + mainctx = g_source_get_context (source); + } + + g_signal_connect (client, "closed", (GCallback) unmanage_client, cctx); + priv->clients = g_list_prepend (priv->clients, cctx); + priv->clients_cookie++; + + gst_rtsp_client_attach (client, mainctx); + + GST_RTSP_SERVER_UNLOCK (server); +} + +static GstRTSPClient * +default_create_client (GstRTSPServer * server) +{ + GstRTSPClient *client; + GstRTSPServerPrivate *priv = server->priv; + + /* a new client connected, create a session to handle the client. */ + client = gst_rtsp_client_new (); + + /* set the session pool that this client should use */ + GST_RTSP_SERVER_LOCK (server); + gst_rtsp_client_set_session_pool (client, priv->session_pool); + /* set the mount points that this client should use */ + gst_rtsp_client_set_mount_points (client, priv->mount_points); + /* set authentication manager */ + gst_rtsp_client_set_auth (client, priv->auth); + /* set threadpool */ + gst_rtsp_client_set_thread_pool (client, priv->thread_pool); + GST_RTSP_SERVER_UNLOCK (server); + + return client; +} + +/** + * gst_rtsp_server_transfer_connection: + * @server: a #GstRTSPServer + * @socket: (transfer full): a network socket + * @ip: the IP address of the remote client + * @port: the port used by the other end + * @initial_buffer: any initial data that was already read from the socket + * + * Take an existing network socket and use it for an RTSP connection. This + * is used when transferring a socket from an HTTP server which should be used + * as an RTSP over HTTP tunnel. The @initial_buffer contains any remaining data + * that the HTTP server read from the socket while parsing the HTTP header. + * + * Returns: TRUE if all was ok, FALSE if an error occurred. + */ +gboolean +gst_rtsp_server_transfer_connection (GstRTSPServer * server, GSocket * socket, + const gchar * ip, gint port, const gchar * initial_buffer) +{ + GstRTSPClient *client = NULL; + GstRTSPServerClass *klass; + GstRTSPConnection *conn; + GstRTSPResult res; + + klass = GST_RTSP_SERVER_GET_CLASS (server); + + if (klass->create_client) + client = klass->create_client (server); + if (client == NULL) + goto client_failed; + + GST_RTSP_CHECK (gst_rtsp_connection_create_from_socket (socket, ip, port, + initial_buffer, &conn), no_connection); + g_object_unref (socket); + + /* set connection on the client now */ + gst_rtsp_client_set_connection (client, conn); + + /* manage the client connection */ + manage_client (server, client); + + return TRUE; + + /* ERRORS */ +client_failed: + { + GST_ERROR_OBJECT (server, "failed to create a client"); + g_object_unref (socket); + return FALSE; + } +no_connection: + { + gchar *str = gst_rtsp_strresult (res); + GST_ERROR ("could not create connection from socket %p: %s", socket, str); + g_free (str); + g_object_unref (socket); + return FALSE; + } +} + +/** + * gst_rtsp_server_io_func: + * @socket: a #GSocket + * @condition: the condition on @source + * @server: (transfer none): a #GstRTSPServer + * + * A default #GSocketSourceFunc that creates a new #GstRTSPClient to accept and handle a + * new connection on @socket or @server. + * + * Returns: TRUE if the source could be connected, FALSE if an error occurred. + */ +gboolean +gst_rtsp_server_io_func (GSocket * socket, GIOCondition condition, + GstRTSPServer * server) +{ + GstRTSPServerPrivate *priv = server->priv; + GstRTSPClient *client = NULL; + GstRTSPServerClass *klass; + GstRTSPResult res; + GstRTSPConnection *conn = NULL; + GstRTSPContext ctx = { NULL }; + + if (condition & G_IO_IN) { + /* a new client connected. */ + GST_RTSP_CHECK (gst_rtsp_connection_accept (socket, &conn, NULL), + accept_failed); + + ctx.server = server; + ctx.conn = conn; + ctx.auth = priv->auth; + gst_rtsp_context_push_current (&ctx); + + if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_CONNECT)) + goto connection_refused; + + klass = GST_RTSP_SERVER_GET_CLASS (server); + /* a new client connected, create a client object to handle the client. */ + if (klass->create_client) + client = klass->create_client (server); + if (client == NULL) + goto client_failed; + + /* set connection on the client now */ + gst_rtsp_client_set_connection (client, conn); + + /* manage the client connection */ + manage_client (server, client); + } else { + GST_WARNING_OBJECT (server, "received unknown event %08x", condition); + } +exit: + gst_rtsp_context_pop_current (&ctx); + + return G_SOURCE_CONTINUE; + + /* ERRORS */ +accept_failed: + { + gchar *str = gst_rtsp_strresult (res); + GST_ERROR_OBJECT (server, "Could not accept client on socket %p: %s", + socket, str); + g_free (str); + goto exit; + } +connection_refused: + { + GST_ERROR_OBJECT (server, "connection refused"); + gst_rtsp_connection_free (conn); + goto exit; + } +client_failed: + { + GST_ERROR_OBJECT (server, "failed to create a client"); + gst_rtsp_connection_free (conn); + goto exit; + } +} + +static void +watch_destroyed (GstRTSPServer * server) +{ + GstRTSPServerPrivate *priv = server->priv; + + GST_DEBUG_OBJECT (server, "source destroyed"); + + g_object_unref (priv->socket); + priv->socket = NULL; + g_object_unref (server); +} + +/** + * gst_rtsp_server_create_source: + * @server: a #GstRTSPServer + * @cancellable: (allow-none): a #GCancellable or %NULL. + * @error: (out): a #GError + * + * Create a #GSource for @server. The new source will have a default + * #GSocketSourceFunc of gst_rtsp_server_io_func(). + * + * @cancellable if not %NULL can be used to cancel the source, which will cause + * the source to trigger, reporting the current condition (which is likely 0 + * unless cancellation happened at the same time as a condition change). You can + * check for this in the callback using g_cancellable_is_cancelled(). + * + * Returns: (transfer full): the #GSource for @server or %NULL when an error + * occurred. Free with g_source_unref () + */ +GSource * +gst_rtsp_server_create_source (GstRTSPServer * server, + GCancellable * cancellable, GError ** error) +{ + GstRTSPServerPrivate *priv; + GSocket *socket, *old; + GSource *source; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); + + priv = server->priv; + + socket = gst_rtsp_server_create_socket (server, NULL, error); + if (socket == NULL) + goto no_socket; + + GST_RTSP_SERVER_LOCK (server); + old = priv->socket; + priv->socket = g_object_ref (socket); + GST_RTSP_SERVER_UNLOCK (server); + + if (old) + g_object_unref (old); + + /* create a watch for reads (new connections) and possible errors */ + source = g_socket_create_source (socket, G_IO_IN | + G_IO_ERR | G_IO_HUP | G_IO_NVAL, cancellable); + g_object_unref (socket); + + /* configure the callback */ + g_source_set_callback (source, + (GSourceFunc) gst_rtsp_server_io_func, g_object_ref (server), + (GDestroyNotify) watch_destroyed); + + return source; + +no_socket: + { + GST_ERROR_OBJECT (server, "failed to create socket"); + return NULL; + } +} + +/** + * gst_rtsp_server_attach: + * @server: a #GstRTSPServer + * @context: (allow-none): a #GMainContext + * + * Attaches @server to @context. When the mainloop for @context is run, the + * server will be dispatched. When @context is %NULL, the default context will be + * used). + * + * This function should be called when the server properties and urls are fully + * configured and the server is ready to start. + * + * Returns: the ID (greater than 0) for the source within the GMainContext. + */ +guint +gst_rtsp_server_attach (GstRTSPServer * server, GMainContext * context) +{ + guint res; + GSource *source; + GError *error = NULL; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), 0); + + source = gst_rtsp_server_create_source (server, NULL, &error); + if (source == NULL) + goto no_source; + + res = g_source_attach (source, context); + g_source_unref (source); + + return res; + + /* ERRORS */ +no_source: + { + GST_ERROR_OBJECT (server, "failed to create watch: %s", error->message); + g_error_free (error); + return 0; + } +} + +/** + * gst_rtsp_server_client_filter: + * @server: a #GstRTSPServer + * @func: (scope call) (allow-none): a callback + * @user_data: user data passed to @func + * + * Call @func for each client managed by @server. The result value of @func + * determines what happens to the client. @func will be called with @server + * locked so no further actions on @server can be performed from @func. + * + * If @func returns #GST_RTSP_FILTER_REMOVE, the client will be removed from + * @server. + * + * If @func returns #GST_RTSP_FILTER_KEEP, the client will remain in @server. + * + * If @func returns #GST_RTSP_FILTER_REF, the client will remain in @server but + * will also be added with an additional ref to the result #GList of this + * function.. + * + * When @func is %NULL, #GST_RTSP_FILTER_REF will be assumed for each client. + * + * Returns: (element-type GstRTSPClient) (transfer full): a #GList with all + * clients for which @func returned #GST_RTSP_FILTER_REF. After usage, each + * element in the #GList should be unreffed before the list is freed. + */ +GList * +gst_rtsp_server_client_filter (GstRTSPServer * server, + GstRTSPServerClientFilterFunc func, gpointer user_data) +{ + GstRTSPServerPrivate *priv; + GList *result, *walk, *next; + GHashTable *visited; + guint cookie; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); + + priv = server->priv; + + result = NULL; + if (func) + visited = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL); + + GST_RTSP_SERVER_LOCK (server); +restart: + cookie = priv->clients_cookie; + for (walk = priv->clients; walk; walk = next) { + ClientContext *cctx = walk->data; + GstRTSPClient *client = cctx->client; + GstRTSPFilterResult res; + gboolean changed; + + next = g_list_next (walk); + + if (func) { + /* only visit each media once */ + if (g_hash_table_contains (visited, client)) + continue; + + g_hash_table_add (visited, g_object_ref (client)); + GST_RTSP_SERVER_UNLOCK (server); + + res = func (server, client, user_data); + + GST_RTSP_SERVER_LOCK (server); + } else + res = GST_RTSP_FILTER_REF; + + changed = (cookie != priv->clients_cookie); + + switch (res) { + case GST_RTSP_FILTER_REMOVE: + GST_RTSP_SERVER_UNLOCK (server); + + gst_rtsp_client_close (client); + + GST_RTSP_SERVER_LOCK (server); + changed |= (cookie != priv->clients_cookie); + break; + case GST_RTSP_FILTER_REF: + result = g_list_prepend (result, g_object_ref (client)); + break; + case GST_RTSP_FILTER_KEEP: + default: + break; + } + if (changed) + goto restart; + } + GST_RTSP_SERVER_UNLOCK (server); + + if (func) + g_hash_table_unref (visited); + + return result; +} diff --git a/gst/rtsp-server/rtsp-server.h b/gst/rtsp-server/rtsp-server.h new file mode 100644 index 0000000..9a6f9d4 --- /dev/null +++ b/gst/rtsp-server/rtsp-server.h @@ -0,0 +1,169 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#ifndef __GST_RTSP_SERVER_H__ +#define __GST_RTSP_SERVER_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GstRTSPServer GstRTSPServer; +typedef struct _GstRTSPServerClass GstRTSPServerClass; +typedef struct _GstRTSPServerPrivate GstRTSPServerPrivate; + +#include "rtsp-session-pool.h" +#include "rtsp-session.h" +#include "rtsp-media.h" +#include "rtsp-stream.h" +#include "rtsp-stream-transport.h" +#include "rtsp-address-pool.h" +#include "rtsp-thread-pool.h" +#include "rtsp-client.h" +#include "rtsp-context.h" +#include "rtsp-server.h" +#include "rtsp-mount-points.h" +#include "rtsp-media-factory.h" +#include "rtsp-permissions.h" +#include "rtsp-auth.h" +#include "rtsp-token.h" +#include "rtsp-session-media.h" +#include "rtsp-sdp.h" +#include "rtsp-media-factory-uri.h" +#include "rtsp-params.h" + +#define GST_TYPE_RTSP_SERVER (gst_rtsp_server_get_type ()) +#define GST_IS_RTSP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_SERVER)) +#define GST_IS_RTSP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_SERVER)) +#define GST_RTSP_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_SERVER, GstRTSPServerClass)) +#define GST_RTSP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_SERVER, GstRTSPServer)) +#define GST_RTSP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_SERVER, GstRTSPServerClass)) +#define GST_RTSP_SERVER_CAST(obj) ((GstRTSPServer*)(obj)) +#define GST_RTSP_SERVER_CLASS_CAST(klass) ((GstRTSPServerClass*)(klass)) + +/** + * GstRTSPServer: + * + * This object listens on a port, creates and manages the clients connected to + * it. + */ +struct _GstRTSPServer { + GObject parent; + + /*< private >*/ + GstRTSPServerPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPServerClass: + * @create_client: Create, configure a new GstRTSPClient + * object that handles the new connection on @socket. The default + * implementation will create a GstRTSPClient and will configure the + * mount-points, auth, session-pool and thread-pool on the client. + * @client_connected: emited when a new client connected. + * + * The RTSP server class structure + */ +struct _GstRTSPServerClass { + GObjectClass parent_class; + + GstRTSPClient * (*create_client) (GstRTSPServer *server); + + /* signals */ + void (*client_connected) (GstRTSPServer *server, GstRTSPClient *client); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +GType gst_rtsp_server_get_type (void); + +GstRTSPServer * gst_rtsp_server_new (void); + +void gst_rtsp_server_set_address (GstRTSPServer *server, const gchar *address); +gchar * gst_rtsp_server_get_address (GstRTSPServer *server); + +void gst_rtsp_server_set_service (GstRTSPServer *server, const gchar *service); +gchar * gst_rtsp_server_get_service (GstRTSPServer *server); + +void gst_rtsp_server_set_backlog (GstRTSPServer *server, gint backlog); +gint gst_rtsp_server_get_backlog (GstRTSPServer *server); + +int gst_rtsp_server_get_bound_port (GstRTSPServer *server); + +void gst_rtsp_server_set_session_pool (GstRTSPServer *server, GstRTSPSessionPool *pool); +GstRTSPSessionPool * gst_rtsp_server_get_session_pool (GstRTSPServer *server); + +void gst_rtsp_server_set_mount_points (GstRTSPServer *server, GstRTSPMountPoints *mounts); +GstRTSPMountPoints * gst_rtsp_server_get_mount_points (GstRTSPServer *server); + +void gst_rtsp_server_set_auth (GstRTSPServer *server, GstRTSPAuth *auth); +GstRTSPAuth * gst_rtsp_server_get_auth (GstRTSPServer *server); + +void gst_rtsp_server_set_thread_pool (GstRTSPServer *server, GstRTSPThreadPool *pool); +GstRTSPThreadPool * gst_rtsp_server_get_thread_pool (GstRTSPServer *server); + +gboolean gst_rtsp_server_transfer_connection (GstRTSPServer * server, GSocket *socket, + const gchar * ip, gint port, + const gchar *initial_buffer); + +gboolean gst_rtsp_server_io_func (GSocket *socket, GIOCondition condition, + GstRTSPServer *server); + +GSocket * gst_rtsp_server_create_socket (GstRTSPServer *server, + GCancellable *cancellable, + GError **error); +GSource * gst_rtsp_server_create_source (GstRTSPServer *server, + GCancellable * cancellable, + GError **error); +guint gst_rtsp_server_attach (GstRTSPServer *server, + GMainContext *context); + +/** + * GstRTSPServerClientFilterFunc: + * @server: a #GstRTSPServer object + * @client: a #GstRTSPClient in @server + * @user_data: user data that has been given to gst_rtsp_server_client_filter() + * + * This function will be called by the gst_rtsp_server_client_filter(). An + * implementation should return a value of #GstRTSPFilterResult. + * + * When this function returns #GST_RTSP_FILTER_REMOVE, @client will be removed + * from @server. + * + * A return value of #GST_RTSP_FILTER_KEEP will leave @client untouched in + * @server. + * + * A value of #GST_RTSP_FILTER_REF will add @client to the result #GList of + * gst_rtsp_server_client_filter(). + * + * Returns: a #GstRTSPFilterResult. + */ +typedef GstRTSPFilterResult (*GstRTSPServerClientFilterFunc) (GstRTSPServer *server, + GstRTSPClient *client, + gpointer user_data); + +GList * gst_rtsp_server_client_filter (GstRTSPServer *server, + GstRTSPServerClientFilterFunc func, + gpointer user_data); + +G_END_DECLS + +#endif /* __GST_RTSP_SERVER_H__ */ diff --git a/gst/rtsp-server/rtsp-session-media.c b/gst/rtsp-server/rtsp-session-media.c new file mode 100644 index 0000000..8eb1f28 --- /dev/null +++ b/gst/rtsp-server/rtsp-session-media.c @@ -0,0 +1,505 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-session-media + * @short_description: Media managed in a session + * @see_also: #GstRTSPMedia, #GstRTSPSession + * + * The #GstRTSPSessionMedia object manages a #GstRTSPMedia with a given path. + * + * With gst_rtsp_session_media_get_transport() and + * gst_rtsp_session_media_set_transport() the transports of a #GstRTSPStream of + * the managed #GstRTSPMedia can be retrieved and configured. + * + * Use gst_rtsp_session_media_set_state() to control the media state and + * transports. + * + * Last reviewed on 2013-07-16 (1.0.0) + */ + +#include + +#include "rtsp-session.h" + +#define GST_RTSP_SESSION_MEDIA_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SESSION_MEDIA, GstRTSPSessionMediaPrivate)) + +struct _GstRTSPSessionMediaPrivate +{ + GMutex lock; + gchar *path; /* unmutable */ + gint path_len; /* unmutable */ + GstRTSPMedia *media; /* unmutable */ + GstRTSPState state; /* protected by lock */ + guint counter; /* protected by lock */ + + GPtrArray *transports; /* protected by lock */ +}; + +enum +{ + PROP_0, + PROP_LAST +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_session_media_debug); +#define GST_CAT_DEFAULT rtsp_session_media_debug + +static void gst_rtsp_session_media_finalize (GObject * obj); + +G_DEFINE_TYPE (GstRTSPSessionMedia, gst_rtsp_session_media, G_TYPE_OBJECT); + +static void +gst_rtsp_session_media_class_init (GstRTSPSessionMediaClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPSessionMediaPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = gst_rtsp_session_media_finalize; + + GST_DEBUG_CATEGORY_INIT (rtsp_session_media_debug, "rtspsessionmedia", 0, + "GstRTSPSessionMedia"); +} + +static void +gst_rtsp_session_media_init (GstRTSPSessionMedia * media) +{ + GstRTSPSessionMediaPrivate *priv = GST_RTSP_SESSION_MEDIA_GET_PRIVATE (media); + + media->priv = priv; + + g_mutex_init (&priv->lock); + priv->state = GST_RTSP_STATE_INIT; +} + +static void +gst_rtsp_session_media_finalize (GObject * obj) +{ + GstRTSPSessionMedia *media; + GstRTSPSessionMediaPrivate *priv; + + media = GST_RTSP_SESSION_MEDIA (obj); + priv = media->priv; + + GST_INFO ("free session media %p", media); + + gst_rtsp_session_media_set_state (media, GST_STATE_NULL); + + g_ptr_array_unref (priv->transports); + + g_free (priv->path); + g_object_unref (priv->media); + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (gst_rtsp_session_media_parent_class)->finalize (obj); +} + +static void +free_session_media (gpointer data) +{ + if (data) + g_object_unref (data); +} + +/** + * gst_rtsp_session_media_new: + * @path: the path + * @media: (transfer full): the #GstRTSPMedia + * + * Create a new #GstRTSPSessionMedia that manages the streams + * in @media for @path. @media should be prepared. + * + * Ownership is taken of @media. + * + * Returns: (transfer full): a new #GstRTSPSessionMedia. + */ +GstRTSPSessionMedia * +gst_rtsp_session_media_new (const gchar * path, GstRTSPMedia * media) +{ + GstRTSPSessionMediaPrivate *priv; + GstRTSPSessionMedia *result; + guint n_streams; + GstRTSPMediaStatus status; + + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); + status = gst_rtsp_media_get_status (media); + g_return_val_if_fail (status == GST_RTSP_MEDIA_STATUS_PREPARED || status == + GST_RTSP_MEDIA_STATUS_SUSPENDED, NULL); + + result = g_object_new (GST_TYPE_RTSP_SESSION_MEDIA, NULL); + priv = result->priv; + + priv->path = g_strdup (path); + priv->path_len = strlen (path); + priv->media = media; + + /* prealloc the streams now, filled with NULL */ + n_streams = gst_rtsp_media_n_streams (media); + priv->transports = g_ptr_array_new_full (n_streams, free_session_media); + g_ptr_array_set_size (priv->transports, n_streams); + + return result; +} + +/** + * gst_rtsp_session_media_matches: + * @media: a #GstRTSPSessionMedia + * @path: a path + * @matched: (out): the amount of matched characters of @path + * + * Check if the path of @media matches @path. It @path matches, the amount of + * matched characters is returned in @matched. + * + * Returns: %TRUE when @path matches the path of @media. + */ +gboolean +gst_rtsp_session_media_matches (GstRTSPSessionMedia * media, + const gchar * path, gint * matched) +{ + GstRTSPSessionMediaPrivate *priv; + gint len; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE); + g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (matched != NULL, FALSE); + + priv = media->priv; + len = strlen (path); + + /* path needs to be smaller than the media path */ + if (len < priv->path_len) + return FALSE; + + /* if media path is larger, it there should be a / following the path */ + if (len > priv->path_len && path[priv->path_len] != '/') + return FALSE; + + *matched = priv->path_len; + + return strncmp (path, priv->path, priv->path_len) == 0; +} + +/** + * gst_rtsp_session_media_get_media: + * @media: a #GstRTSPSessionMedia + * + * Get the #GstRTSPMedia that was used when constructing @media + * + * Returns: (transfer none): the #GstRTSPMedia of @media. Remains valid as long + * as @media is valid. + */ +GstRTSPMedia * +gst_rtsp_session_media_get_media (GstRTSPSessionMedia * media) +{ + g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL); + + return media->priv->media; +} + +/** + * gst_rtsp_session_media_get_base_time: + * @media: a #GstRTSPSessionMedia + * + * Get the base_time of the #GstRTSPMedia in @media + * + * Returns: the base_time of the media. + */ +GstClockTime +gst_rtsp_session_media_get_base_time (GstRTSPSessionMedia * media) +{ + g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), GST_CLOCK_TIME_NONE); + + return gst_rtsp_media_get_base_time (media->priv->media); +} + +/** + * gst_rtsp_session_media_get_rtpinfo: + * @media: a #GstRTSPSessionMedia + * + * Retrieve the RTP-Info header string for all streams in @media + * with configured transports. + * + * Returns: (transfer full) (nullable): The RTP-Info as a string or + * %NULL when no RTP-Info could be generated, g_free() after usage. + */ +gchar * +gst_rtsp_session_media_get_rtpinfo (GstRTSPSessionMedia * media) +{ + GstRTSPSessionMediaPrivate *priv; + GString *rtpinfo = NULL; + GstRTSPStreamTransport *transport; + GstRTSPStream *stream; + guint i, n_streams; + GstClockTime earliest = GST_CLOCK_TIME_NONE; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL); + + priv = media->priv; + g_mutex_lock (&priv->lock); + + if (gst_rtsp_media_get_status (priv->media) != GST_RTSP_MEDIA_STATUS_PREPARED) + goto not_prepared; + + n_streams = priv->transports->len; + + /* first step, take lowest running-time from all streams */ + GST_LOG_OBJECT (media, "determining start time among %d transports", + n_streams); + + for (i = 0; i < n_streams; i++) { + GstClockTime running_time; + + transport = g_ptr_array_index (priv->transports, i); + if (transport == NULL) { + GST_DEBUG_OBJECT (media, "ignoring unconfigured transport %d", i); + continue; + } + + stream = gst_rtsp_stream_transport_get_stream (transport); + if (!gst_rtsp_stream_get_rtpinfo (stream, NULL, NULL, NULL, &running_time)) + continue; + + GST_LOG_OBJECT (media, "running time of %d stream: %" GST_TIME_FORMAT, i, + GST_TIME_ARGS (running_time)); + + if (!GST_CLOCK_TIME_IS_VALID (earliest)) { + earliest = running_time; + } else { + earliest = MIN (earliest, running_time); + } + } + + GST_LOG_OBJECT (media, "media start time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (earliest)); + + /* next step, scale all rtptime of all streams to lowest running-time */ + GST_LOG_OBJECT (media, "collecting RTP info for %d transports", n_streams); + + for (i = 0; i < n_streams; i++) { + gchar *stream_rtpinfo; + + transport = g_ptr_array_index (priv->transports, i); + if (transport == NULL) { + GST_DEBUG_OBJECT (media, "ignoring unconfigured transport %d", i); + continue; + } + + stream_rtpinfo = + gst_rtsp_stream_transport_get_rtpinfo (transport, earliest); + if (stream_rtpinfo == NULL) { + GST_DEBUG_OBJECT (media, "ignoring unknown RTPInfo %d", i); + continue; + } + + if (rtpinfo == NULL) + rtpinfo = g_string_new (""); + else + g_string_append (rtpinfo, ", "); + + g_string_append (rtpinfo, stream_rtpinfo); + g_free (stream_rtpinfo); + } + g_mutex_unlock (&priv->lock); + + if (rtpinfo == NULL) { + GST_WARNING_OBJECT (media, "RTP info is empty"); + return NULL; + } + return g_string_free (rtpinfo, FALSE); + + /* ERRORS */ +not_prepared: + { + g_mutex_unlock (&priv->lock); + GST_ERROR_OBJECT (media, "media was not prepared"); + return NULL; + } +} + +/** + * gst_rtsp_session_media_set_transport: + * @media: a #GstRTSPSessionMedia + * @stream: a #GstRTSPStream + * @tr: (transfer full): a #GstRTSPTransport + * + * Configure the transport for @stream to @tr in @media. + * + * Returns: (transfer none): the new or updated #GstRTSPStreamTransport for @stream. + */ +GstRTSPStreamTransport * +gst_rtsp_session_media_set_transport (GstRTSPSessionMedia * media, + GstRTSPStream * stream, GstRTSPTransport * tr) +{ + GstRTSPSessionMediaPrivate *priv; + GstRTSPStreamTransport *result; + guint idx; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL); + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + g_return_val_if_fail (tr != NULL, NULL); + priv = media->priv; + idx = gst_rtsp_stream_get_index (stream); + g_return_val_if_fail (idx < priv->transports->len, NULL); + + g_mutex_lock (&priv->lock); + result = g_ptr_array_index (priv->transports, idx); + if (result == NULL) { + result = gst_rtsp_stream_transport_new (stream, tr); + g_ptr_array_index (priv->transports, idx) = result; + g_mutex_unlock (&priv->lock); + } else { + gst_rtsp_stream_transport_set_transport (result, tr); + g_mutex_unlock (&priv->lock); + } + + return result; +} + +/** + * gst_rtsp_session_media_get_transport: + * @media: a #GstRTSPSessionMedia + * @idx: the stream index + * + * Get a previously created #GstRTSPStreamTransport for the stream at @idx. + * + * Returns: (transfer none): a #GstRTSPStreamTransport that is valid until the + * session of @media is unreffed. + */ +GstRTSPStreamTransport * +gst_rtsp_session_media_get_transport (GstRTSPSessionMedia * media, guint idx) +{ + GstRTSPSessionMediaPrivate *priv; + GstRTSPStreamTransport *result; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL); + priv = media->priv; + g_return_val_if_fail (idx < priv->transports->len, NULL); + + g_mutex_lock (&priv->lock); + result = g_ptr_array_index (priv->transports, idx); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_session_media_alloc_channels: + * @media: a #GstRTSPSessionMedia + * @range: (out): a #GstRTSPRange + * + * Fill @range with the next available min and max channels for + * interleaved transport. + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_session_media_alloc_channels (GstRTSPSessionMedia * media, + GstRTSPRange * range) +{ + GstRTSPSessionMediaPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + range->min = priv->counter++; + range->max = priv->counter++; + g_mutex_unlock (&priv->lock); + + return TRUE; +} + +/** + * gst_rtsp_session_media_set_state: + * @media: a #GstRTSPSessionMedia + * @state: the new state + * + * Tell the media object @media to change to @state. + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_session_media_set_state (GstRTSPSessionMedia * media, GstState state) +{ + GstRTSPSessionMediaPrivate *priv; + gboolean ret; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + ret = gst_rtsp_media_set_state (priv->media, state, priv->transports); + g_mutex_unlock (&priv->lock); + + return ret; +} + +/** + * gst_rtsp_session_media_set_rtsp_state: + * @media: a #GstRTSPSessionMedia + * @state: a #GstRTSPState + * + * Set the RTSP state of @media to @state. + */ +void +gst_rtsp_session_media_set_rtsp_state (GstRTSPSessionMedia * media, + GstRTSPState state) +{ + GstRTSPSessionMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_SESSION_MEDIA (media)); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + priv->state = state; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_session_media_get_rtsp_state: + * @media: a #GstRTSPSessionMedia + * + * Get the current RTSP state of @media. + * + * Returns: the current RTSP state of @media. + */ +GstRTSPState +gst_rtsp_session_media_get_rtsp_state (GstRTSPSessionMedia * media) +{ + GstRTSPSessionMediaPrivate *priv; + GstRTSPState ret; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), + GST_RTSP_STATE_INVALID); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + ret = priv->state; + g_mutex_unlock (&priv->lock); + + return ret; +} diff --git a/gst/rtsp-server/rtsp-session-media.h b/gst/rtsp-server/rtsp-session-media.h new file mode 100644 index 0000000..e2af5ad --- /dev/null +++ b/gst/rtsp-server/rtsp-session-media.h @@ -0,0 +1,97 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + +#ifndef __GST_RTSP_SESSION_MEDIA_H__ +#define __GST_RTSP_SESSION_MEDIA_H__ + +G_BEGIN_DECLS + +#define GST_TYPE_RTSP_SESSION_MEDIA (gst_rtsp_session_media_get_type ()) +#define GST_IS_RTSP_SESSION_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_SESSION_MEDIA)) +#define GST_IS_RTSP_SESSION_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_SESSION_MEDIA)) +#define GST_RTSP_SESSION_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_SESSION_MEDIA, GstRTSPSessionMediaClass)) +#define GST_RTSP_SESSION_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_SESSION_MEDIA, GstRTSPSessionMedia)) +#define GST_RTSP_SESSION_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_SESSION_MEDIA, GstRTSPSessionMediaClass)) +#define GST_RTSP_SESSION_MEDIA_CAST(obj) ((GstRTSPSessionMedia*)(obj)) +#define GST_RTSP_SESSION_MEDIA_CLASS_CAST(klass) ((GstRTSPSessionMediaClass*)(klass)) + +typedef struct _GstRTSPSessionMedia GstRTSPSessionMedia; +typedef struct _GstRTSPSessionMediaClass GstRTSPSessionMediaClass; +typedef struct _GstRTSPSessionMediaPrivate GstRTSPSessionMediaPrivate; + +/** + * GstRTSPSessionMedia: + * + * State of a client session regarding a specific media identified by path. + */ +struct _GstRTSPSessionMedia +{ + GObject parent; + + /*< private >*/ + GstRTSPSessionMediaPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstRTSPSessionMediaClass +{ + GObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_rtsp_session_media_get_type (void); + +GstRTSPSessionMedia * gst_rtsp_session_media_new (const gchar *path, + GstRTSPMedia *media); + +gboolean gst_rtsp_session_media_matches (GstRTSPSessionMedia *media, + const gchar *path, + gint * matched); +GstRTSPMedia * gst_rtsp_session_media_get_media (GstRTSPSessionMedia *media); + +GstClockTime gst_rtsp_session_media_get_base_time (GstRTSPSessionMedia *media); +/* control media */ +gboolean gst_rtsp_session_media_set_state (GstRTSPSessionMedia *media, + GstState state); + +void gst_rtsp_session_media_set_rtsp_state (GstRTSPSessionMedia *media, + GstRTSPState state); +GstRTSPState gst_rtsp_session_media_get_rtsp_state (GstRTSPSessionMedia *media); + +/* get stream transport config */ +GstRTSPStreamTransport * gst_rtsp_session_media_set_transport (GstRTSPSessionMedia *media, + GstRTSPStream *stream, + GstRTSPTransport *tr); +GstRTSPStreamTransport * gst_rtsp_session_media_get_transport (GstRTSPSessionMedia *media, + guint idx); + +gboolean gst_rtsp_session_media_alloc_channels (GstRTSPSessionMedia *media, + GstRTSPRange *range); + +gchar * gst_rtsp_session_media_get_rtpinfo (GstRTSPSessionMedia * media); + +G_END_DECLS + +#endif /* __GST_RTSP_SESSION_MEDIA_H__ */ diff --git a/gst/rtsp-server/rtsp-session-pool.c b/gst/rtsp-server/rtsp-session-pool.c new file mode 100644 index 0000000..fad5288 --- /dev/null +++ b/gst/rtsp-server/rtsp-session-pool.c @@ -0,0 +1,765 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-session-pool + * @short_description: An object for managing sessions + * @see_also: #GstRTSPSession + * + * The #GstRTSPSessionPool object manages a list of #GstRTSPSession objects. + * + * The maximum number of sessions can be configured with + * gst_rtsp_session_pool_set_max_sessions(). The current number of sessions can + * be retrieved with gst_rtsp_session_pool_get_n_sessions(). + * + * Use gst_rtsp_session_pool_create() to create a new #GstRTSPSession object. + * The session object can be found again with its id and + * gst_rtsp_session_pool_find(). + * + * All sessions can be iterated with gst_rtsp_session_pool_filter(). + * + * Run gst_rtsp_session_pool_cleanup() periodically to remove timed out sessions + * or use gst_rtsp_session_pool_create_watch() to be notified when session + * cleanup should be performed. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include "rtsp-session-pool.h" + +#define GST_RTSP_SESSION_POOL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SESSION_POOL, GstRTSPSessionPoolPrivate)) + +struct _GstRTSPSessionPoolPrivate +{ + GMutex lock; /* protects everything in this struct */ + guint max_sessions; + GHashTable *sessions; + guint sessions_cookie; +}; + +#define DEFAULT_MAX_SESSIONS 0 + +enum +{ + PROP_0, + PROP_MAX_SESSIONS, + PROP_LAST +}; + +static const gchar session_id_charset[] = + { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '$', '-', '_', '.', '+' +}; + +enum +{ + SIGNAL_SESSION_REMOVED, + SIGNAL_LAST +}; + +static guint gst_rtsp_session_pool_signals[SIGNAL_LAST] = { 0 }; + +GST_DEBUG_CATEGORY_STATIC (rtsp_session_debug); +#define GST_CAT_DEFAULT rtsp_session_debug + +static void gst_rtsp_session_pool_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_session_pool_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); +static void gst_rtsp_session_pool_finalize (GObject * object); + +static gchar *create_session_id (GstRTSPSessionPool * pool); +static GstRTSPSession *create_session (GstRTSPSessionPool * pool, + const gchar * id); + +G_DEFINE_TYPE (GstRTSPSessionPool, gst_rtsp_session_pool, G_TYPE_OBJECT); + +static void +gst_rtsp_session_pool_class_init (GstRTSPSessionPoolClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPSessionPoolPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gst_rtsp_session_pool_get_property; + gobject_class->set_property = gst_rtsp_session_pool_set_property; + gobject_class->finalize = gst_rtsp_session_pool_finalize; + + g_object_class_install_property (gobject_class, PROP_MAX_SESSIONS, + g_param_spec_uint ("max-sessions", "Max Sessions", + "the maximum amount of sessions (0 = unlimited)", + 0, G_MAXUINT, DEFAULT_MAX_SESSIONS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_rtsp_session_pool_signals[SIGNAL_SESSION_REMOVED] = + g_signal_new ("session-removed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPSessionPoolClass, + session_removed), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, + 1, GST_TYPE_RTSP_SESSION); + + klass->create_session_id = create_session_id; + klass->create_session = create_session; + + GST_DEBUG_CATEGORY_INIT (rtsp_session_debug, "rtspsessionpool", 0, + "GstRTSPSessionPool"); +} + +static void +gst_rtsp_session_pool_init (GstRTSPSessionPool * pool) +{ + GstRTSPSessionPoolPrivate *priv = GST_RTSP_SESSION_POOL_GET_PRIVATE (pool); + + pool->priv = priv; + + g_mutex_init (&priv->lock); + priv->sessions = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, g_object_unref); + priv->max_sessions = DEFAULT_MAX_SESSIONS; +} + +static GstRTSPFilterResult +remove_sessions_func (GstRTSPSessionPool * pool, GstRTSPSession * session, + gpointer user_data) +{ + return GST_RTSP_FILTER_REMOVE; +} + +static void +gst_rtsp_session_pool_finalize (GObject * object) +{ + GstRTSPSessionPool *pool = GST_RTSP_SESSION_POOL (object); + GstRTSPSessionPoolPrivate *priv = pool->priv; + + gst_rtsp_session_pool_filter (pool, remove_sessions_func, NULL); + g_hash_table_unref (priv->sessions); + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (gst_rtsp_session_pool_parent_class)->finalize (object); +} + +static void +gst_rtsp_session_pool_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + GstRTSPSessionPool *pool = GST_RTSP_SESSION_POOL (object); + + switch (propid) { + case PROP_MAX_SESSIONS: + g_value_set_uint (value, gst_rtsp_session_pool_get_max_sessions (pool)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + break; + } +} + +static void +gst_rtsp_session_pool_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + GstRTSPSessionPool *pool = GST_RTSP_SESSION_POOL (object); + + switch (propid) { + case PROP_MAX_SESSIONS: + gst_rtsp_session_pool_set_max_sessions (pool, g_value_get_uint (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + break; + } +} + +/** + * gst_rtsp_session_pool_new: + * + * Create a new #GstRTSPSessionPool instance. + * + * Returns: (transfer full): A new #GstRTSPSessionPool. g_object_unref() after + * usage. + */ +GstRTSPSessionPool * +gst_rtsp_session_pool_new (void) +{ + GstRTSPSessionPool *result; + + result = g_object_new (GST_TYPE_RTSP_SESSION_POOL, NULL); + + return result; +} + +/** + * gst_rtsp_session_pool_set_max_sessions: + * @pool: a #GstRTSPSessionPool + * @max: the maximum number of sessions + * + * Configure the maximum allowed number of sessions in @pool to @max. + * A value of 0 means an unlimited amount of sessions. + */ +void +gst_rtsp_session_pool_set_max_sessions (GstRTSPSessionPool * pool, guint max) +{ + GstRTSPSessionPoolPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_SESSION_POOL (pool)); + + priv = pool->priv; + + g_mutex_lock (&priv->lock); + priv->max_sessions = max; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_session_pool_get_max_sessions: + * @pool: a #GstRTSPSessionPool + * + * Get the maximum allowed number of sessions in @pool. 0 means an unlimited + * amount of sessions. + * + * Returns: the maximum allowed number of sessions. + */ +guint +gst_rtsp_session_pool_get_max_sessions (GstRTSPSessionPool * pool) +{ + GstRTSPSessionPoolPrivate *priv; + guint result; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), 0); + + priv = pool->priv; + + g_mutex_lock (&priv->lock); + result = priv->max_sessions; + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_session_pool_get_n_sessions: + * @pool: a #GstRTSPSessionPool + * + * Get the amount of active sessions in @pool. + * + * Returns: the amount of active sessions in @pool. + */ +guint +gst_rtsp_session_pool_get_n_sessions (GstRTSPSessionPool * pool) +{ + GstRTSPSessionPoolPrivate *priv; + guint result; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), 0); + + priv = pool->priv; + + g_mutex_lock (&priv->lock); + result = g_hash_table_size (priv->sessions); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_session_pool_find: + * @pool: the pool to search + * @sessionid: the session id + * + * Find the session with @sessionid in @pool. The access time of the session + * will be updated with gst_rtsp_session_touch(). + * + * Returns: (transfer full) (nullable): the #GstRTSPSession with @sessionid + * or %NULL when the session did not exist. g_object_unref() after usage. + */ +GstRTSPSession * +gst_rtsp_session_pool_find (GstRTSPSessionPool * pool, const gchar * sessionid) +{ + GstRTSPSessionPoolPrivate *priv; + GstRTSPSession *result; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL); + g_return_val_if_fail (sessionid != NULL, NULL); + + priv = pool->priv; + + g_mutex_lock (&priv->lock); + result = g_hash_table_lookup (priv->sessions, sessionid); + if (result) { + g_object_ref (result); + gst_rtsp_session_touch (result); + } + g_mutex_unlock (&priv->lock); + + return result; +} + +static gchar * +create_session_id (GstRTSPSessionPool * pool) +{ + gchar id[17]; + gint i; + + for (i = 0; i < 16; i++) { + id[i] = + session_id_charset[g_random_int_range (0, + G_N_ELEMENTS (session_id_charset))]; + } + id[16] = 0; + + return g_uri_escape_string (id, NULL, FALSE); +} + +static GstRTSPSession * +create_session (GstRTSPSessionPool * pool, const gchar * id) +{ + return gst_rtsp_session_new (id); +} + +/** + * gst_rtsp_session_pool_create: + * @pool: a #GstRTSPSessionPool + * + * Create a new #GstRTSPSession object in @pool. + * + * Returns: (transfer full): a new #GstRTSPSession. + */ +GstRTSPSession * +gst_rtsp_session_pool_create (GstRTSPSessionPool * pool) +{ + GstRTSPSessionPoolPrivate *priv; + GstRTSPSession *result = NULL; + GstRTSPSessionPoolClass *klass; + gchar *id = NULL; + guint retry; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL); + + priv = pool->priv; + + klass = GST_RTSP_SESSION_POOL_GET_CLASS (pool); + + retry = 0; + do { + /* start by creating a new random session id, we assume that this is random + * enough to not cause a collision, which we will check later */ + if (klass->create_session_id) + id = klass->create_session_id (pool); + else + goto no_function; + + if (id == NULL) + goto no_session; + + g_mutex_lock (&priv->lock); + /* check session limit */ + if (priv->max_sessions > 0) { + if (g_hash_table_size (priv->sessions) >= priv->max_sessions) + goto too_many_sessions; + } + /* check if the sessionid existed */ + result = g_hash_table_lookup (priv->sessions, id); + if (result) { + /* found, retry with a different session id */ + result = NULL; + retry++; + if (retry > 100) + goto collision; + } else { + /* not found, create session and insert it in the pool */ + if (klass->create_session) + result = create_session (pool, id); + if (result == NULL) + goto too_many_sessions; + /* take additional ref for the pool */ + g_object_ref (result); + g_hash_table_insert (priv->sessions, + (gchar *) gst_rtsp_session_get_sessionid (result), result); + priv->sessions_cookie++; + } + g_mutex_unlock (&priv->lock); + + g_free (id); + } while (result == NULL); + + return result; + + /* ERRORS */ +no_function: + { + GST_WARNING ("no create_session_id vmethod in GstRTSPSessionPool %p", pool); + return NULL; + } +no_session: + { + GST_WARNING ("can't create session id with GstRTSPSessionPool %p", pool); + return NULL; + } +collision: + { + GST_WARNING ("can't find unique sessionid for GstRTSPSessionPool %p", pool); + g_mutex_unlock (&priv->lock); + g_free (id); + return NULL; + } +too_many_sessions: + { + GST_WARNING ("session pool reached max sessions of %d", priv->max_sessions); + g_mutex_unlock (&priv->lock); + g_free (id); + return NULL; + } +} + +/** + * gst_rtsp_session_pool_remove: + * @pool: a #GstRTSPSessionPool + * @sess: (transfer none): a #GstRTSPSession + * + * Remove @sess from @pool, releasing the ref that the pool has on @sess. + * + * Returns: %TRUE if the session was found and removed. + */ +gboolean +gst_rtsp_session_pool_remove (GstRTSPSessionPool * pool, GstRTSPSession * sess) +{ + GstRTSPSessionPoolPrivate *priv; + gboolean found; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), FALSE); + g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), FALSE); + + priv = pool->priv; + + g_mutex_lock (&priv->lock); + g_object_ref (sess); + found = + g_hash_table_remove (priv->sessions, + gst_rtsp_session_get_sessionid (sess)); + if (found) + priv->sessions_cookie++; + g_mutex_unlock (&priv->lock); + + if (found) + g_signal_emit (pool, gst_rtsp_session_pool_signals[SIGNAL_SESSION_REMOVED], + 0, sess); + + g_object_unref (sess); + + return found; +} + +typedef struct +{ + GTimeVal now; + GstRTSPSessionPool *pool; + GList *removed; +} CleanupData; + +static gboolean +cleanup_func (gchar * sessionid, GstRTSPSession * sess, CleanupData * data) +{ + gboolean expired; + + expired = gst_rtsp_session_is_expired (sess, &data->now); + if (expired) { + GST_DEBUG ("session expired"); + data->removed = g_list_prepend (data->removed, g_object_ref (sess)); + } + return expired; +} + +/** + * gst_rtsp_session_pool_cleanup: + * @pool: a #GstRTSPSessionPool + * + * Inspect all the sessions in @pool and remove the sessions that are inactive + * for more than their timeout. + * + * Returns: the amount of sessions that got removed. + */ +guint +gst_rtsp_session_pool_cleanup (GstRTSPSessionPool * pool) +{ + GstRTSPSessionPoolPrivate *priv; + guint result; + CleanupData data; + GList *walk; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), 0); + + priv = pool->priv; + + g_get_current_time (&data.now); + data.pool = pool; + data.removed = NULL; + + g_mutex_lock (&priv->lock); + result = + g_hash_table_foreach_remove (priv->sessions, (GHRFunc) cleanup_func, + &data); + if (result > 0) + priv->sessions_cookie++; + g_mutex_unlock (&priv->lock); + + for (walk = data.removed; walk; walk = walk->next) { + GstRTSPSession *sess = walk->data; + + g_signal_emit (pool, + gst_rtsp_session_pool_signals[SIGNAL_SESSION_REMOVED], 0, sess); + + g_object_unref (sess); + } + g_list_free (data.removed); + + return result; +} + +/** + * gst_rtsp_session_pool_filter: + * @pool: a #GstRTSPSessionPool + * @func: (scope call) (allow-none): a callback + * @user_data: (closure): user data passed to @func + * + * Call @func for each session in @pool. The result value of @func determines + * what happens to the session. @func will be called with the session pool + * locked so no further actions on @pool can be performed from @func. + * + * If @func returns #GST_RTSP_FILTER_REMOVE, the session will be set to the + * expired state with gst_rtsp_session_set_expired() and removed from + * @pool. + * + * If @func returns #GST_RTSP_FILTER_KEEP, the session will remain in @pool. + * + * If @func returns #GST_RTSP_FILTER_REF, the session will remain in @pool but + * will also be added with an additional ref to the result GList of this + * function.. + * + * When @func is %NULL, #GST_RTSP_FILTER_REF will be assumed for all sessions. + * + * Returns: (element-type GstRTSPSession) (transfer full): a GList with all + * sessions for which @func returned #GST_RTSP_FILTER_REF. After usage, each + * element in the GList should be unreffed before the list is freed. + */ +GList * +gst_rtsp_session_pool_filter (GstRTSPSessionPool * pool, + GstRTSPSessionPoolFilterFunc func, gpointer user_data) +{ + GstRTSPSessionPoolPrivate *priv; + GHashTableIter iter; + gpointer key, value; + GList *result; + GHashTable *visited; + guint cookie; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL); + + priv = pool->priv; + + result = NULL; + if (func) + visited = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL); + + g_mutex_lock (&priv->lock); +restart: + g_hash_table_iter_init (&iter, priv->sessions); + cookie = priv->sessions_cookie; + while (g_hash_table_iter_next (&iter, &key, &value)) { + GstRTSPSession *session = value; + GstRTSPFilterResult res; + gboolean changed; + + if (func) { + /* only visit each session once */ + if (g_hash_table_contains (visited, session)) + continue; + + g_hash_table_add (visited, g_object_ref (session)); + g_mutex_unlock (&priv->lock); + + res = func (pool, session, user_data); + + g_mutex_lock (&priv->lock); + } else + res = GST_RTSP_FILTER_REF; + + changed = (cookie != priv->sessions_cookie); + + switch (res) { + case GST_RTSP_FILTER_REMOVE: + { + gboolean removed = TRUE; + + if (changed) + /* something changed, check if we still have the session */ + removed = g_hash_table_remove (priv->sessions, key); + else + g_hash_table_iter_remove (&iter); + + if (removed) { + /* if we managed to remove the session, update the cookie and + * signal */ + cookie = ++priv->sessions_cookie; + g_mutex_unlock (&priv->lock); + + g_signal_emit (pool, + gst_rtsp_session_pool_signals[SIGNAL_SESSION_REMOVED], 0, + session); + + g_mutex_lock (&priv->lock); + /* cookie could have changed again, make sure we restart */ + changed |= (cookie != priv->sessions_cookie); + } + break; + } + case GST_RTSP_FILTER_REF: + /* keep ref */ + result = g_list_prepend (result, g_object_ref (session)); + break; + case GST_RTSP_FILTER_KEEP: + default: + break; + } + if (changed) + goto restart; + } + g_mutex_unlock (&priv->lock); + + if (func) + g_hash_table_unref (visited); + + return result; +} + +typedef struct +{ + GSource source; + GstRTSPSessionPool *pool; + gint timeout; +} GstPoolSource; + +static void +collect_timeout (gchar * sessionid, GstRTSPSession * sess, GstPoolSource * psrc) +{ + gint timeout; + GTimeVal now; + + g_get_current_time (&now); + + timeout = gst_rtsp_session_next_timeout (sess, &now); + GST_INFO ("%p: next timeout: %d", sess, timeout); + if (psrc->timeout == -1 || timeout < psrc->timeout) + psrc->timeout = timeout; +} + +static gboolean +gst_pool_source_prepare (GSource * source, gint * timeout) +{ + GstRTSPSessionPoolPrivate *priv; + GstPoolSource *psrc; + gboolean result; + + psrc = (GstPoolSource *) source; + psrc->timeout = -1; + priv = psrc->pool->priv; + + g_mutex_lock (&priv->lock); + g_hash_table_foreach (priv->sessions, (GHFunc) collect_timeout, psrc); + g_mutex_unlock (&priv->lock); + + if (timeout) + *timeout = psrc->timeout; + + result = psrc->timeout == 0; + + GST_INFO ("prepare %d, %d", psrc->timeout, result); + + return result; +} + +static gboolean +gst_pool_source_check (GSource * source) +{ + GST_INFO ("check"); + + return gst_pool_source_prepare (source, NULL); +} + +static gboolean +gst_pool_source_dispatch (GSource * source, GSourceFunc callback, + gpointer user_data) +{ + gboolean res; + GstPoolSource *psrc = (GstPoolSource *) source; + GstRTSPSessionPoolFunc func = (GstRTSPSessionPoolFunc) callback; + + GST_INFO ("dispatch"); + + if (func) + res = func (psrc->pool, user_data); + else + res = FALSE; + + return res; +} + +static void +gst_pool_source_finalize (GSource * source) +{ + GstPoolSource *psrc = (GstPoolSource *) source; + + GST_INFO ("finalize %p", psrc); + + g_object_unref (psrc->pool); + psrc->pool = NULL; +} + +static GSourceFuncs gst_pool_source_funcs = { + gst_pool_source_prepare, + gst_pool_source_check, + gst_pool_source_dispatch, + gst_pool_source_finalize +}; + +/** + * gst_rtsp_session_pool_create_watch: + * @pool: a #GstRTSPSessionPool + * + * Create a #GSource that will be dispatched when the session should be cleaned + * up. + * + * Returns: (transfer full): a #GSource + */ +GSource * +gst_rtsp_session_pool_create_watch (GstRTSPSessionPool * pool) +{ + GstPoolSource *source; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL); + + source = (GstPoolSource *) g_source_new (&gst_pool_source_funcs, + sizeof (GstPoolSource)); + source->pool = g_object_ref (pool); + + return (GSource *) source; +} diff --git a/gst/rtsp-server/rtsp-session-pool.h b/gst/rtsp-server/rtsp-session-pool.h new file mode 100644 index 0000000..e2ba951 --- /dev/null +++ b/gst/rtsp-server/rtsp-session-pool.h @@ -0,0 +1,143 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#ifndef __GST_RTSP_SESSION_POOL_H__ +#define __GST_RTSP_SESSION_POOL_H__ + +G_BEGIN_DECLS + +typedef struct _GstRTSPSessionPool GstRTSPSessionPool; +typedef struct _GstRTSPSessionPoolClass GstRTSPSessionPoolClass; +typedef struct _GstRTSPSessionPoolPrivate GstRTSPSessionPoolPrivate; + +#include "rtsp-session.h" + +#define GST_TYPE_RTSP_SESSION_POOL (gst_rtsp_session_pool_get_type ()) +#define GST_IS_RTSP_SESSION_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_SESSION_POOL)) +#define GST_IS_RTSP_SESSION_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_SESSION_POOL)) +#define GST_RTSP_SESSION_POOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_SESSION_POOL, GstRTSPSessionPoolClass)) +#define GST_RTSP_SESSION_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_SESSION_POOL, GstRTSPSessionPool)) +#define GST_RTSP_SESSION_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_SESSION_POOL, GstRTSPSessionPoolClass)) +#define GST_RTSP_SESSION_POOL_CAST(obj) ((GstRTSPSessionPool*)(obj)) +#define GST_RTSP_SESSION_POOL_CLASS_CAST(klass) ((GstRTSPSessionPoolClass*)(klass)) + +/** + * GstRTSPSessionPool: + * + * An object that keeps track of the active sessions. This object is usually + * attached to a #GstRTSPServer object to manage the sessions in that server. + */ +struct _GstRTSPSessionPool { + GObject parent; + + /*< private >*/ + GstRTSPSessionPoolPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPSessionPoolClass: + * @create_session_id: create a new random session id. Subclasses can create + * custom session ids and should not check if the session exists. + * @create_session: make a new session object. + * @session_removed: a session was removed from the pool + */ +struct _GstRTSPSessionPoolClass { + GObjectClass parent_class; + + gchar * (*create_session_id) (GstRTSPSessionPool *pool); + GstRTSPSession * (*create_session) (GstRTSPSessionPool *pool, const gchar *id); + + /* signals */ + void (*session_removed) (GstRTSPSessionPool *pool, + GstRTSPSession *session); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE - 1]; +}; + +/** + * GstRTSPSessionPoolFunc: + * @pool: a #GstRTSPSessionPool object + * @user_data: user data that has been given when registering the handler + * + * The function that will be called from the GSource watch on the session pool. + * + * The function will be called when the pool must be cleaned up because one or + * more sessions timed out. + * + * Returns: %FALSE if the source should be removed. + */ +typedef gboolean (*GstRTSPSessionPoolFunc) (GstRTSPSessionPool *pool, gpointer user_data); + +/** + * GstRTSPSessionPoolFilterFunc: + * @pool: a #GstRTSPSessionPool object + * @session: a #GstRTSPSession in @pool + * @user_data: user data that has been given to gst_rtsp_session_pool_filter() + * + * This function will be called by the gst_rtsp_session_pool_filter(). An + * implementation should return a value of #GstRTSPFilterResult. + * + * When this function returns #GST_RTSP_FILTER_REMOVE, @session will be removed + * from @pool. + * + * A return value of #GST_RTSP_FILTER_KEEP will leave @session untouched in + * @pool. + * + * A value of GST_RTSP_FILTER_REF will add @session to the result #GList of + * gst_rtsp_session_pool_filter(). + * + * Returns: a #GstRTSPFilterResult. + */ +typedef GstRTSPFilterResult (*GstRTSPSessionPoolFilterFunc) (GstRTSPSessionPool *pool, + GstRTSPSession *session, + gpointer user_data); + + +GType gst_rtsp_session_pool_get_type (void); + +/* creating a session pool */ +GstRTSPSessionPool * gst_rtsp_session_pool_new (void); + +/* counting sessions */ +void gst_rtsp_session_pool_set_max_sessions (GstRTSPSessionPool *pool, guint max); +guint gst_rtsp_session_pool_get_max_sessions (GstRTSPSessionPool *pool); + +guint gst_rtsp_session_pool_get_n_sessions (GstRTSPSessionPool *pool); + +/* managing sessions */ +GstRTSPSession * gst_rtsp_session_pool_create (GstRTSPSessionPool *pool); +GstRTSPSession * gst_rtsp_session_pool_find (GstRTSPSessionPool *pool, + const gchar *sessionid); +gboolean gst_rtsp_session_pool_remove (GstRTSPSessionPool *pool, + GstRTSPSession *sess); + +/* perform session maintenance */ +GList * gst_rtsp_session_pool_filter (GstRTSPSessionPool *pool, + GstRTSPSessionPoolFilterFunc func, + gpointer user_data); +guint gst_rtsp_session_pool_cleanup (GstRTSPSessionPool *pool); +GSource * gst_rtsp_session_pool_create_watch (GstRTSPSessionPool *pool); + +G_END_DECLS + +#endif /* __GST_RTSP_SESSION_POOL_H__ */ diff --git a/gst/rtsp-server/rtsp-session.c b/gst/rtsp-server/rtsp-session.c new file mode 100644 index 0000000..372746a --- /dev/null +++ b/gst/rtsp-server/rtsp-session.c @@ -0,0 +1,649 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-session + * @short_description: An object to manage media + * @see_also: #GstRTSPSessionPool, #GstRTSPSessionMedia, #GstRTSPMedia + * + * The #GstRTSPSession is identified by an id, unique in the + * #GstRTSPSessionPool that created the session and manages media and its + * configuration. + * + * A #GstRTSPSession has a timeout that can be retrieved with + * gst_rtsp_session_get_timeout(). You can check if the sessions is expired with + * gst_rtsp_session_is_expired(). gst_rtsp_session_touch() will reset the + * expiration counter of the session. + * + * When a client configures a media with SETUP, a session will be created to + * keep track of the configuration of that media. With + * gst_rtsp_session_manage_media(), the media is added to the managed media + * in the session. With gst_rtsp_session_release_media() the media can be + * released again from the session. Managed media is identified in the sessions + * with a url. Use gst_rtsp_session_get_media() to get the media that matches + * (part of) the given url. + * + * The media in a session can be iterated with gst_rtsp_session_filter(). + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include + +#include "rtsp-session.h" + +#define GST_RTSP_SESSION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SESSION, GstRTSPSessionPrivate)) + +struct _GstRTSPSessionPrivate +{ + GMutex lock; /* protects everything but sessionid and create_time */ + gchar *sessionid; + + guint timeout; + gboolean timeout_always_visible; + GTimeVal create_time; /* immutable */ + GTimeVal last_access; + gint expire_count; + + GList *medias; + guint medias_cookie; +}; + +#undef DEBUG + +#define DEFAULT_TIMEOUT 60 +#define DEFAULT_ALWAYS_VISIBLE FALSE + +enum +{ + PROP_0, + PROP_SESSIONID, + PROP_TIMEOUT, + PROP_TIMEOUT_ALWAYS_VISIBLE, + PROP_LAST +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_session_debug); +#define GST_CAT_DEFAULT rtsp_session_debug + +static void gst_rtsp_session_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_session_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); +static void gst_rtsp_session_finalize (GObject * obj); + +G_DEFINE_TYPE (GstRTSPSession, gst_rtsp_session, G_TYPE_OBJECT); + +static void +gst_rtsp_session_class_init (GstRTSPSessionClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPSessionPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gst_rtsp_session_get_property; + gobject_class->set_property = gst_rtsp_session_set_property; + gobject_class->finalize = gst_rtsp_session_finalize; + + g_object_class_install_property (gobject_class, PROP_SESSIONID, + g_param_spec_string ("sessionid", "Sessionid", "the session id", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_TIMEOUT, + g_param_spec_uint ("timeout", "timeout", + "the timeout of the session (0 = never)", 0, G_MAXUINT, + DEFAULT_TIMEOUT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_TIMEOUT_ALWAYS_VISIBLE, + g_param_spec_boolean ("timeout-always-visible", "Timeout Always Visible ", + "timeout always visible in header", + DEFAULT_ALWAYS_VISIBLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + GST_DEBUG_CATEGORY_INIT (rtsp_session_debug, "rtspsession", 0, + "GstRTSPSession"); +} + +static void +gst_rtsp_session_init (GstRTSPSession * session) +{ + GstRTSPSessionPrivate *priv = GST_RTSP_SESSION_GET_PRIVATE (session); + + session->priv = priv; + + GST_INFO ("init session %p", session); + + g_mutex_init (&priv->lock); + priv->timeout = DEFAULT_TIMEOUT; + g_get_current_time (&priv->create_time); + gst_rtsp_session_touch (session); +} + +static void +gst_rtsp_session_finalize (GObject * obj) +{ + GstRTSPSession *session; + GstRTSPSessionPrivate *priv; + + session = GST_RTSP_SESSION (obj); + priv = session->priv; + + GST_INFO ("finalize session %p", session); + + /* free all media */ + g_list_free_full (priv->medias, g_object_unref); + + /* free session id */ + g_free (priv->sessionid); + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (gst_rtsp_session_parent_class)->finalize (obj); +} + +static void +gst_rtsp_session_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + GstRTSPSession *session = GST_RTSP_SESSION (object); + GstRTSPSessionPrivate *priv = session->priv; + + switch (propid) { + case PROP_SESSIONID: + g_value_set_string (value, priv->sessionid); + break; + case PROP_TIMEOUT: + g_value_set_uint (value, gst_rtsp_session_get_timeout (session)); + break; + case PROP_TIMEOUT_ALWAYS_VISIBLE: + g_value_set_boolean (value, priv->timeout_always_visible); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_session_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + GstRTSPSession *session = GST_RTSP_SESSION (object); + GstRTSPSessionPrivate *priv = session->priv; + + switch (propid) { + case PROP_SESSIONID: + g_free (priv->sessionid); + priv->sessionid = g_value_dup_string (value); + break; + case PROP_TIMEOUT: + gst_rtsp_session_set_timeout (session, g_value_get_uint (value)); + break; + case PROP_TIMEOUT_ALWAYS_VISIBLE: + g_mutex_lock (&priv->lock); + priv->timeout_always_visible = g_value_get_boolean (value); + g_mutex_unlock (&priv->lock); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +/** + * gst_rtsp_session_manage_media: + * @sess: a #GstRTSPSession + * @path: the path for the media + * @media: (transfer full): a #GstRTSPMedia + * + * Manage the media object @obj in @sess. @path will be used to retrieve this + * media from the session with gst_rtsp_session_get_media(). + * + * Ownership is taken from @media. + * + * Returns: (transfer none): a new @GstRTSPSessionMedia object. + */ +GstRTSPSessionMedia * +gst_rtsp_session_manage_media (GstRTSPSession * sess, const gchar * path, + GstRTSPMedia * media) +{ + GstRTSPSessionPrivate *priv; + GstRTSPSessionMedia *result; + GstRTSPMediaStatus status; + + g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL); + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); + status = gst_rtsp_media_get_status (media); + g_return_val_if_fail (status == GST_RTSP_MEDIA_STATUS_PREPARED || status == + GST_RTSP_MEDIA_STATUS_SUSPENDED, NULL); + + priv = sess->priv; + + result = gst_rtsp_session_media_new (path, media); + + g_mutex_lock (&priv->lock); + priv->medias = g_list_prepend (priv->medias, result); + priv->medias_cookie++; + g_mutex_unlock (&priv->lock); + + GST_INFO ("manage new media %p in session %p", media, result); + + return result; +} + +/** + * gst_rtsp_session_release_media: + * @sess: a #GstRTSPSession + * @media: (transfer none): a #GstRTSPMedia + * + * Release the managed @media in @sess, freeing the memory allocated by it. + * + * Returns: %TRUE if there are more media session left in @sess. + */ +gboolean +gst_rtsp_session_release_media (GstRTSPSession * sess, + GstRTSPSessionMedia * media) +{ + GstRTSPSessionPrivate *priv; + GList *find; + gboolean more; + + g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), FALSE); + g_return_val_if_fail (media != NULL, FALSE); + + priv = sess->priv; + + g_mutex_lock (&priv->lock); + find = g_list_find (priv->medias, media); + if (find) { + priv->medias = g_list_delete_link (priv->medias, find); + priv->medias_cookie++; + } + more = (priv->medias != NULL); + g_mutex_unlock (&priv->lock); + + if (find) + g_object_unref (media); + + return more; +} + +/** + * gst_rtsp_session_get_media: + * @sess: a #GstRTSPSession + * @path: the path for the media + * @matched: (out): the amount of matched characters + * + * Get the session media for @path. @matched will contain the number of matched + * characters of @path. + * + * Returns: (transfer none): the configuration for @path in @sess. + */ +GstRTSPSessionMedia * +gst_rtsp_session_get_media (GstRTSPSession * sess, const gchar * path, + gint * matched) +{ + GstRTSPSessionPrivate *priv; + GstRTSPSessionMedia *result; + GList *walk; + gint best; + + g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL); + g_return_val_if_fail (path != NULL, NULL); + + priv = sess->priv; + result = NULL; + best = 0; + + g_mutex_lock (&priv->lock); + for (walk = priv->medias; walk; walk = g_list_next (walk)) { + GstRTSPSessionMedia *test; + + test = (GstRTSPSessionMedia *) walk->data; + + /* find largest match */ + if (gst_rtsp_session_media_matches (test, path, matched)) { + if (best < *matched) { + result = test; + best = *matched; + } + } + } + g_mutex_unlock (&priv->lock); + + *matched = best; + + return result; +} + +/** + * gst_rtsp_session_filter: + * @sess: a #GstRTSPSession + * @func: (scope call) (allow-none): a callback + * @user_data: (closure): user data passed to @func + * + * Call @func for each media in @sess. The result value of @func determines + * what happens to the media. @func will be called with @sess + * locked so no further actions on @sess can be performed from @func. + * + * If @func returns #GST_RTSP_FILTER_REMOVE, the media will be removed from + * @sess. + * + * If @func returns #GST_RTSP_FILTER_KEEP, the media will remain in @sess. + * + * If @func returns #GST_RTSP_FILTER_REF, the media will remain in @sess but + * will also be added with an additional ref to the result #GList of this + * function.. + * + * When @func is %NULL, #GST_RTSP_FILTER_REF will be assumed for all media. + * + * Returns: (element-type GstRTSPSessionMedia) (transfer full): a GList with all + * media for which @func returned #GST_RTSP_FILTER_REF. After usage, each + * element in the #GList should be unreffed before the list is freed. + */ +GList * +gst_rtsp_session_filter (GstRTSPSession * sess, + GstRTSPSessionFilterFunc func, gpointer user_data) +{ + GstRTSPSessionPrivate *priv; + GList *result, *walk, *next; + GHashTable *visited; + guint cookie; + + g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL); + + priv = sess->priv; + + result = NULL; + if (func) + visited = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL); + + g_mutex_lock (&priv->lock); +restart: + cookie = priv->medias_cookie; + for (walk = priv->medias; walk; walk = next) { + GstRTSPSessionMedia *media = walk->data; + GstRTSPFilterResult res; + gboolean changed; + + next = g_list_next (walk); + + if (func) { + /* only visit each media once */ + if (g_hash_table_contains (visited, media)) + continue; + + g_hash_table_add (visited, g_object_ref (media)); + g_mutex_unlock (&priv->lock); + + res = func (sess, media, user_data); + + g_mutex_lock (&priv->lock); + } else + res = GST_RTSP_FILTER_REF; + + changed = (cookie != priv->medias_cookie); + + switch (res) { + case GST_RTSP_FILTER_REMOVE: + if (changed) + priv->medias = g_list_remove (priv->medias, media); + else + priv->medias = g_list_delete_link (priv->medias, walk); + cookie = ++priv->medias_cookie; + g_object_unref (media); + break; + case GST_RTSP_FILTER_REF: + result = g_list_prepend (result, g_object_ref (media)); + break; + case GST_RTSP_FILTER_KEEP: + default: + break; + } + if (changed) + goto restart; + } + g_mutex_unlock (&priv->lock); + + if (func) + g_hash_table_unref (visited); + + return result; +} + +/** + * gst_rtsp_session_new: + * @sessionid: a session id + * + * Create a new #GstRTSPSession instance with @sessionid. + * + * Returns: (transfer full): a new #GstRTSPSession + */ +GstRTSPSession * +gst_rtsp_session_new (const gchar * sessionid) +{ + GstRTSPSession *result; + + g_return_val_if_fail (sessionid != NULL, NULL); + + result = g_object_new (GST_TYPE_RTSP_SESSION, "sessionid", sessionid, NULL); + + return result; +} + +/** + * gst_rtsp_session_get_sessionid: + * @session: a #GstRTSPSession + * + * Get the sessionid of @session. + * + * Returns: (transfer none): the sessionid of @session. The value remains valid + * as long as @session is alive. + */ +const gchar * +gst_rtsp_session_get_sessionid (GstRTSPSession * session) +{ + g_return_val_if_fail (GST_IS_RTSP_SESSION (session), NULL); + + return session->priv->sessionid; +} + +/** + * gst_rtsp_session_get_header: + * @session: a #GstRTSPSession + * + * Get the string that can be placed in the Session header field. + * + * Returns: (transfer full): the Session header of @session. g_free() after usage. + */ +gchar * +gst_rtsp_session_get_header (GstRTSPSession * session) +{ + GstRTSPSessionPrivate *priv; + gchar *result; + + g_return_val_if_fail (GST_IS_RTSP_SESSION (session), NULL); + + priv = session->priv; + + + g_mutex_lock (&priv->lock); + if (priv->timeout_always_visible || priv->timeout != 60) + result = g_strdup_printf ("%s; timeout=%d", priv->sessionid, priv->timeout); + else + result = g_strdup (priv->sessionid); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_session_set_timeout: + * @session: a #GstRTSPSession + * @timeout: the new timeout + * + * Configure @session for a timeout of @timeout seconds. The session will be + * cleaned up when there is no activity for @timeout seconds. + */ +void +gst_rtsp_session_set_timeout (GstRTSPSession * session, guint timeout) +{ + GstRTSPSessionPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_SESSION (session)); + + priv = session->priv; + + g_mutex_lock (&priv->lock); + priv->timeout = timeout; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_session_get_timeout: + * @session: a #GstRTSPSession + * + * Get the timeout value of @session. + * + * Returns: the timeout of @session in seconds. + */ +guint +gst_rtsp_session_get_timeout (GstRTSPSession * session) +{ + GstRTSPSessionPrivate *priv; + guint res; + + g_return_val_if_fail (GST_IS_RTSP_SESSION (session), 0); + + priv = session->priv; + + g_mutex_lock (&priv->lock); + res = priv->timeout; + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_session_touch: + * @session: a #GstRTSPSession + * + * Update the last_access time of the session to the current time. + */ +void +gst_rtsp_session_touch (GstRTSPSession * session) +{ + GstRTSPSessionPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_SESSION (session)); + + priv = session->priv; + + g_mutex_lock (&priv->lock); + g_get_current_time (&priv->last_access); + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_session_prevent_expire: + * @session: a #GstRTSPSession + * + * Prevent @session from expiring. + */ +void +gst_rtsp_session_prevent_expire (GstRTSPSession * session) +{ + g_return_if_fail (GST_IS_RTSP_SESSION (session)); + + g_atomic_int_add (&session->priv->expire_count, 1); +} + +/** + * gst_rtsp_session_allow_expire: + * @session: a #GstRTSPSession + * + * Allow @session to expire. This method must be called an equal + * amount of time as gst_rtsp_session_prevent_expire(). + */ +void +gst_rtsp_session_allow_expire (GstRTSPSession * session) +{ + g_atomic_int_add (&session->priv->expire_count, -1); +} + +/** + * gst_rtsp_session_next_timeout: + * @session: a #GstRTSPSession + * @now: (transfer none): the current system time + * + * Get the amount of milliseconds till the session will expire. + * + * Returns: the amount of milliseconds since the session will time out. + */ +gint +gst_rtsp_session_next_timeout (GstRTSPSession * session, GTimeVal * now) +{ + GstRTSPSessionPrivate *priv; + gint res; + GstClockTime last_access, now_ns; + + g_return_val_if_fail (GST_IS_RTSP_SESSION (session), -1); + g_return_val_if_fail (now != NULL, -1); + + priv = session->priv; + + g_mutex_lock (&priv->lock); + if (g_atomic_int_get (&priv->expire_count) != 0) { + /* touch session when the expire count is not 0 */ + g_get_current_time (&priv->last_access); + } + + last_access = GST_TIMEVAL_TO_TIME (priv->last_access); + /* add timeout allow for 5 seconds of extra time */ + last_access += priv->timeout * GST_SECOND + (5 * GST_SECOND); + g_mutex_unlock (&priv->lock); + + now_ns = GST_TIMEVAL_TO_TIME (*now); + + if (last_access > now_ns) + res = GST_TIME_AS_MSECONDS (last_access - now_ns); + else + res = 0; + + return res; +} + +/** + * gst_rtsp_session_is_expired: + * @session: a #GstRTSPSession + * @now: (transfer none): the current system time + * + * Check if @session timeout out. + * + * Returns: %TRUE if @session timed out + */ +gboolean +gst_rtsp_session_is_expired (GstRTSPSession * session, GTimeVal * now) +{ + gboolean res; + + res = (gst_rtsp_session_next_timeout (session, now) == 0); + + return res; +} diff --git a/gst/rtsp-server/rtsp-session.h b/gst/rtsp-server/rtsp-session.h new file mode 100644 index 0000000..d9c0f18 --- /dev/null +++ b/gst/rtsp-server/rtsp-session.h @@ -0,0 +1,143 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + +#ifndef __GST_RTSP_SESSION_H__ +#define __GST_RTSP_SESSION_H__ + +G_BEGIN_DECLS + +#define GST_TYPE_RTSP_SESSION (gst_rtsp_session_get_type ()) +#define GST_IS_RTSP_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_SESSION)) +#define GST_IS_RTSP_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_SESSION)) +#define GST_RTSP_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_SESSION, GstRTSPSessionClass)) +#define GST_RTSP_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_SESSION, GstRTSPSession)) +#define GST_RTSP_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_SESSION, GstRTSPSessionClass)) +#define GST_RTSP_SESSION_CAST(obj) ((GstRTSPSession*)(obj)) +#define GST_RTSP_SESSION_CLASS_CAST(klass) ((GstRTSPSessionClass*)(klass)) + +typedef struct _GstRTSPSession GstRTSPSession; +typedef struct _GstRTSPSessionClass GstRTSPSessionClass; +typedef struct _GstRTSPSessionPrivate GstRTSPSessionPrivate; + +/** + * GstRTSPFilterResult: + * @GST_RTSP_FILTER_REMOVE: Remove session + * @GST_RTSP_FILTER_KEEP: Keep session in the pool + * @GST_RTSP_FILTER_REF: Ref session in the result list + * + * Possible return values for gst_rtsp_session_pool_filter(). + */ +typedef enum +{ + GST_RTSP_FILTER_REMOVE, + GST_RTSP_FILTER_KEEP, + GST_RTSP_FILTER_REF, +} GstRTSPFilterResult; + +#include "rtsp-media.h" +#include "rtsp-session-media.h" + +/** + * GstRTSPSession: + * + * Session information kept by the server for a specific client. + * One client session, identified with a session id, can handle multiple medias + * identified with the url of a media. + */ +struct _GstRTSPSession { + GObject parent; + + /*< private >*/ + GstRTSPSessionPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstRTSPSessionClass { + GObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_rtsp_session_get_type (void); + +/* create a new session */ +GstRTSPSession * gst_rtsp_session_new (const gchar *sessionid); + +const gchar * gst_rtsp_session_get_sessionid (GstRTSPSession *session); + +gchar * gst_rtsp_session_get_header (GstRTSPSession *session); + +void gst_rtsp_session_set_timeout (GstRTSPSession *session, guint timeout); +guint gst_rtsp_session_get_timeout (GstRTSPSession *session); + +/* session timeout stuff */ +void gst_rtsp_session_touch (GstRTSPSession *session); +void gst_rtsp_session_prevent_expire (GstRTSPSession *session); +void gst_rtsp_session_allow_expire (GstRTSPSession *session); +gint gst_rtsp_session_next_timeout (GstRTSPSession *session, GTimeVal *now); +gboolean gst_rtsp_session_is_expired (GstRTSPSession *session, GTimeVal *now); + +/* handle media in a session */ +GstRTSPSessionMedia * gst_rtsp_session_manage_media (GstRTSPSession *sess, + const gchar *path, + GstRTSPMedia *media); +gboolean gst_rtsp_session_release_media (GstRTSPSession *sess, + GstRTSPSessionMedia *media); +/* get media in a session */ +GstRTSPSessionMedia * gst_rtsp_session_get_media (GstRTSPSession *sess, + const gchar *path, + gint * matched); + +/** + * GstRTSPSessionFilterFunc: + * @sess: a #GstRTSPSession object + * @media: a #GstRTSPSessionMedia in @sess + * @user_data: user data that has been given to gst_rtsp_session_filter() + * + * This function will be called by the gst_rtsp_session_filter(). An + * implementation should return a value of #GstRTSPFilterResult. + * + * When this function returns #GST_RTSP_FILTER_REMOVE, @media will be removed + * from @sess. + * + * A return value of #GST_RTSP_FILTER_KEEP will leave @media untouched in + * @sess. + * + * A value of GST_RTSP_FILTER_REF will add @media to the result #GList of + * gst_rtsp_session_filter(). + * + * Returns: a #GstRTSPFilterResult. + */ +typedef GstRTSPFilterResult (*GstRTSPSessionFilterFunc) (GstRTSPSession *sess, + GstRTSPSessionMedia *media, + gpointer user_data); + +GList * gst_rtsp_session_filter (GstRTSPSession *sess, + GstRTSPSessionFilterFunc func, + gpointer user_data); + + +G_END_DECLS + +#endif /* __GST_RTSP_SESSION_H__ */ diff --git a/gst/rtsp-server/rtsp-stream-transport.c b/gst/rtsp-server/rtsp-stream-transport.c new file mode 100644 index 0000000..a99295b --- /dev/null +++ b/gst/rtsp-server/rtsp-stream-transport.c @@ -0,0 +1,503 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-stream-transport + * @short_description: A media stream transport configuration + * @see_also: #GstRTSPStream, #GstRTSPSessionMedia + * + * The #GstRTSPStreamTransport configures the transport used by a + * #GstRTSPStream. It is usually manages by a #GstRTSPSessionMedia object. + * + * With gst_rtsp_stream_transport_set_callbacks(), callbacks can be configured + * to handle the RTP and RTCP packets from the stream, for example when they + * need to be sent over TCP. + * + * With gst_rtsp_stream_transport_set_active() the transports are added and + * removed from the stream. + * + * A #GstRTSPStream will call gst_rtsp_stream_transport_keep_alive() when RTCP + * is received from the client. It will also call + * gst_rtsp_stream_transport_set_timed_out() when a receiver has timed out. + * + * Last reviewed on 2013-07-16 (1.0.0) + */ + +#include +#include + +#include "rtsp-stream-transport.h" + +#define GST_RTSP_STREAM_TRANSPORT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_STREAM_TRANSPORT, GstRTSPStreamTransportPrivate)) + +struct _GstRTSPStreamTransportPrivate +{ + GstRTSPStream *stream; + + GstRTSPSendFunc send_rtp; + GstRTSPSendFunc send_rtcp; + gpointer user_data; + GDestroyNotify notify; + + GstRTSPKeepAliveFunc keep_alive; + gpointer ka_user_data; + GDestroyNotify ka_notify; + gboolean active; + gboolean timed_out; + + GstRTSPTransport *transport; + GstRTSPUrl *url; + + GObject *rtpsource; +}; + +enum +{ + PROP_0, + PROP_LAST +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_stream_transport_debug); +#define GST_CAT_DEFAULT rtsp_stream_transport_debug + +static void gst_rtsp_stream_transport_finalize (GObject * obj); + +G_DEFINE_TYPE (GstRTSPStreamTransport, gst_rtsp_stream_transport, + G_TYPE_OBJECT); + +static void +gst_rtsp_stream_transport_class_init (GstRTSPStreamTransportClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPStreamTransportPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = gst_rtsp_stream_transport_finalize; + + GST_DEBUG_CATEGORY_INIT (rtsp_stream_transport_debug, "rtspmediatransport", + 0, "GstRTSPStreamTransport"); +} + +static void +gst_rtsp_stream_transport_init (GstRTSPStreamTransport * trans) +{ + GstRTSPStreamTransportPrivate *priv = + GST_RTSP_STREAM_TRANSPORT_GET_PRIVATE (trans); + + trans->priv = priv; +} + +static void +gst_rtsp_stream_transport_finalize (GObject * obj) +{ + GstRTSPStreamTransportPrivate *priv; + GstRTSPStreamTransport *trans; + + trans = GST_RTSP_STREAM_TRANSPORT (obj); + priv = trans->priv; + + /* remove callbacks now */ + gst_rtsp_stream_transport_set_callbacks (trans, NULL, NULL, NULL, NULL); + gst_rtsp_stream_transport_set_keepalive (trans, NULL, NULL, NULL); + + if (priv->transport) + gst_rtsp_transport_free (priv->transport); + + if (priv->url) + gst_rtsp_url_free (priv->url); + + G_OBJECT_CLASS (gst_rtsp_stream_transport_parent_class)->finalize (obj); +} + +/** + * gst_rtsp_stream_transport_new: + * @stream: a #GstRTSPStream + * @tr: (transfer full): a GstRTSPTransport + * + * Create a new #GstRTSPStreamTransport that can be used to manage + * @stream with transport @tr. + * + * Returns: (transfer full): a new #GstRTSPStreamTransport + */ +GstRTSPStreamTransport * +gst_rtsp_stream_transport_new (GstRTSPStream * stream, GstRTSPTransport * tr) +{ + GstRTSPStreamTransportPrivate *priv; + GstRTSPStreamTransport *trans; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + g_return_val_if_fail (tr != NULL, NULL); + + trans = g_object_new (GST_TYPE_RTSP_STREAM_TRANSPORT, NULL); + priv = trans->priv; + priv->stream = stream; + priv->transport = tr; + + return trans; +} + +/** + * gst_rtsp_stream_transport_get_stream: + * @trans: a #GstRTSPStreamTransport + * + * Get the #GstRTSPStream used when constructing @trans. + * + * Returns: (transfer none): the stream used when constructing @trans. + */ +GstRTSPStream * +gst_rtsp_stream_transport_get_stream (GstRTSPStreamTransport * trans) +{ + g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL); + + return trans->priv->stream; +} + +/** + * gst_rtsp_stream_transport_set_callbacks: + * @trans: a #GstRTSPStreamTransport + * @send_rtp: (scope notified): a callback called when RTP should be sent + * @send_rtcp: (scope notified): a callback called when RTCP should be sent + * @user_data: (closure): user data passed to callbacks + * @notify: (allow-none): called with the user_data when no longer needed. + * + * Install callbacks that will be called when data for a stream should be sent + * to a client. This is usually used when sending RTP/RTCP over TCP. + */ +void +gst_rtsp_stream_transport_set_callbacks (GstRTSPStreamTransport * trans, + GstRTSPSendFunc send_rtp, GstRTSPSendFunc send_rtcp, + gpointer user_data, GDestroyNotify notify) +{ + GstRTSPStreamTransportPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans)); + + priv = trans->priv; + + priv->send_rtp = send_rtp; + priv->send_rtcp = send_rtcp; + if (priv->notify) + priv->notify (priv->user_data); + priv->user_data = user_data; + priv->notify = notify; +} + +/** + * gst_rtsp_stream_transport_set_keepalive: + * @trans: a #GstRTSPStreamTransport + * @keep_alive: (scope notified): a callback called when the receiver is active + * @user_data: (closure): user data passed to callback + * @notify: (allow-none): called with the user_data when no longer needed. + * + * Install callbacks that will be called when RTCP packets are received from the + * receiver of @trans. + */ +void +gst_rtsp_stream_transport_set_keepalive (GstRTSPStreamTransport * trans, + GstRTSPKeepAliveFunc keep_alive, gpointer user_data, GDestroyNotify notify) +{ + GstRTSPStreamTransportPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans)); + + priv = trans->priv; + + priv->keep_alive = keep_alive; + if (priv->ka_notify) + priv->ka_notify (priv->ka_user_data); + priv->ka_user_data = user_data; + priv->ka_notify = notify; +} + + +/** + * gst_rtsp_stream_transport_set_transport: + * @trans: a #GstRTSPStreamTransport + * @tr: (transfer full): a client #GstRTSPTransport + * + * Set @tr as the client transport. This function takes ownership of the + * passed @tr. + */ +void +gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport * trans, + GstRTSPTransport * tr) +{ + GstRTSPStreamTransportPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans)); + g_return_if_fail (tr != NULL); + + priv = trans->priv; + + /* keep track of the transports in the stream. */ + if (priv->transport) + gst_rtsp_transport_free (priv->transport); + priv->transport = tr; +} + +/** + * gst_rtsp_stream_transport_get_transport: + * @trans: a #GstRTSPStreamTransport + * + * Get the transport configured in @trans. + * + * Returns: (transfer none): the transport configured in @trans. It remains + * valid for as long as @trans is valid. + */ +const GstRTSPTransport * +gst_rtsp_stream_transport_get_transport (GstRTSPStreamTransport * trans) +{ + g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL); + + return trans->priv->transport; +} + +/** + * gst_rtsp_stream_transport_set_url: + * @trans: a #GstRTSPStreamTransport + * @url: (transfer none): a client #GstRTSPUrl + * + * Set @url as the client url. + */ +void +gst_rtsp_stream_transport_set_url (GstRTSPStreamTransport * trans, + const GstRTSPUrl * url) +{ + GstRTSPStreamTransportPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans)); + + priv = trans->priv; + + /* keep track of the transports in the stream. */ + if (priv->url) + gst_rtsp_url_free (priv->url); + priv->url = (url ? gst_rtsp_url_copy (url) : NULL); +} + +/** + * gst_rtsp_stream_transport_get_url: + * @trans: a #GstRTSPStreamTransport + * + * Get the url configured in @trans. + * + * Returns: (transfer none): the url configured in @trans. It remains + * valid for as long as @trans is valid. + */ +const GstRTSPUrl * +gst_rtsp_stream_transport_get_url (GstRTSPStreamTransport * trans) +{ + g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL); + + return trans->priv->url; +} + + /** + * gst_rtsp_stream_transport_get_rtpinfo: + * @trans: a #GstRTSPStreamTransport + * @start_time: a star time + * + * Get the RTP-Info string for @trans and @start_time. + * + * Returns: (transfer full) (nullable): the RTPInfo string for @trans + * and @start_time or %NULL when the RTP-Info could not be + * determined. g_free() after usage. + */ +gchar * +gst_rtsp_stream_transport_get_rtpinfo (GstRTSPStreamTransport * trans, + GstClockTime start_time) +{ + GstRTSPStreamTransportPrivate *priv; + gchar *url_str; + GString *rtpinfo; + guint rtptime, seq, clock_rate; + GstClockTime running_time = GST_CLOCK_TIME_NONE; + + g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL); + + priv = trans->priv; + + if (!gst_rtsp_stream_get_rtpinfo (priv->stream, &rtptime, &seq, &clock_rate, + &running_time)) + return NULL; + + GST_DEBUG ("RTP time %u, seq %u, rate %u, running-time %" GST_TIME_FORMAT, + rtptime, seq, clock_rate, GST_TIME_ARGS (running_time)); + + if (GST_CLOCK_TIME_IS_VALID (running_time) + && GST_CLOCK_TIME_IS_VALID (start_time)) { + if (running_time > start_time) { + rtptime -= + gst_util_uint64_scale_int (running_time - start_time, clock_rate, + GST_SECOND); + } else { + rtptime += + gst_util_uint64_scale_int (start_time - running_time, clock_rate, + GST_SECOND); + } + } + GST_DEBUG ("RTP time %u, for start-time %" GST_TIME_FORMAT, + rtptime, GST_TIME_ARGS (start_time)); + + rtpinfo = g_string_new (""); + + url_str = gst_rtsp_url_get_request_uri (trans->priv->url); + g_string_append_printf (rtpinfo, "url=%s;seq=%u;rtptime=%u", + url_str, seq, rtptime); + g_free (url_str); + + return g_string_free (rtpinfo, FALSE); +} + +/** + * gst_rtsp_stream_transport_set_active: + * @trans: a #GstRTSPStreamTransport + * @active: new state of @trans + * + * Activate or deactivate datatransfer configured in @trans. + * + * Returns: %TRUE when the state was changed. + */ +gboolean +gst_rtsp_stream_transport_set_active (GstRTSPStreamTransport * trans, + gboolean active) +{ + GstRTSPStreamTransportPrivate *priv; + gboolean res; + + g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE); + + priv = trans->priv; + + if (priv->active == active) + return FALSE; + + if (active) + res = gst_rtsp_stream_add_transport (priv->stream, trans); + else + res = gst_rtsp_stream_remove_transport (priv->stream, trans); + + if (res) + priv->active = active; + + return res; +} + +/** + * gst_rtsp_stream_transport_set_timed_out: + * @trans: a #GstRTSPStreamTransport + * @timedout: timed out value + * + * Set the timed out state of @trans to @timedout + */ +void +gst_rtsp_stream_transport_set_timed_out (GstRTSPStreamTransport * trans, + gboolean timedout) +{ + g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans)); + + trans->priv->timed_out = timedout; +} + +/** + * gst_rtsp_stream_transport_is_timed_out: + * @trans: a #GstRTSPStreamTransport + * + * Check if @trans is timed out. + * + * Returns: %TRUE if @trans timed out. + */ +gboolean +gst_rtsp_stream_transport_is_timed_out (GstRTSPStreamTransport * trans) +{ + g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE); + + return trans->priv->timed_out; +} + +/** + * gst_rtsp_stream_transport_send_rtp: + * @trans: a #GstRTSPStreamTransport + * @buffer: (transfer none): a #GstBuffer + * + * Send @buffer to the installed RTP callback for @trans. + * + * Returns: %TRUE on success + */ +gboolean +gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport * trans, + GstBuffer * buffer) +{ + GstRTSPStreamTransportPrivate *priv; + gboolean res = FALSE; + + priv = trans->priv; + + if (priv->send_rtp) + res = + priv->send_rtp (buffer, priv->transport->interleaved.min, + priv->user_data); + + return res; +} + +/** + * gst_rtsp_stream_transport_send_rtcp: + * @trans: a #GstRTSPStreamTransport + * @buffer: (transfer none): a #GstBuffer + * + * Send @buffer to the installed RTCP callback for @trans. + * + * Returns: %TRUE on success + */ +gboolean +gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport * trans, + GstBuffer * buffer) +{ + GstRTSPStreamTransportPrivate *priv; + gboolean res = FALSE; + + priv = trans->priv; + + if (priv->send_rtcp) + res = + priv->send_rtcp (buffer, priv->transport->interleaved.max, + priv->user_data); + + return res; +} + +/** + * gst_rtsp_stream_transport_keep_alive: + * @trans: a #GstRTSPStreamTransport + * + * Signal the installed keep_alive callback for @trans. + */ +void +gst_rtsp_stream_transport_keep_alive (GstRTSPStreamTransport * trans) +{ + GstRTSPStreamTransportPrivate *priv; + + priv = trans->priv; + + if (priv->keep_alive) + priv->keep_alive (priv->ka_user_data); +} diff --git a/gst/rtsp-server/rtsp-stream-transport.h b/gst/rtsp-server/rtsp-stream-transport.h new file mode 100644 index 0000000..7735ee7 --- /dev/null +++ b/gst/rtsp-server/rtsp-stream-transport.h @@ -0,0 +1,133 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include +#include +#include + +#ifndef __GST_RTSP_STREAM_TRANSPORT_H__ +#define __GST_RTSP_STREAM_TRANSPORT_H__ + +G_BEGIN_DECLS + +/* types for the media */ +#define GST_TYPE_RTSP_STREAM_TRANSPORT (gst_rtsp_stream_transport_get_type ()) +#define GST_IS_RTSP_STREAM_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_STREAM_TRANSPORT)) +#define GST_IS_RTSP_STREAM_TRANSPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_STREAM_TRANSPORT)) +#define GST_RTSP_STREAM_TRANSPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_STREAM_TRANSPORT, GstRTSPStreamTransportClass)) +#define GST_RTSP_STREAM_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_STREAM_TRANSPORT, GstRTSPStreamTransport)) +#define GST_RTSP_STREAM_TRANSPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_STREAM_TRANSPORT, GstRTSPStreamTransportClass)) +#define GST_RTSP_STREAM_TRANSPORT_CAST(obj) ((GstRTSPStreamTransport*)(obj)) +#define GST_RTSP_STREAM_TRANSPORT_CLASS_CAST(klass) ((GstRTSPStreamTransportClass*)(klass)) + +typedef struct _GstRTSPStreamTransport GstRTSPStreamTransport; +typedef struct _GstRTSPStreamTransportClass GstRTSPStreamTransportClass; +typedef struct _GstRTSPStreamTransportPrivate GstRTSPStreamTransportPrivate; + +#include "rtsp-stream.h" + +/** + * GstRTSPSendFunc: + * @buffer: a #GstBuffer + * @channel: a channel + * @user_data: user data + * + * Function registered with gst_rtsp_stream_transport_set_callbacks() and + * called when @buffer must be sent on @channel. + * + * Returns: %TRUE on success + */ +typedef gboolean (*GstRTSPSendFunc) (GstBuffer *buffer, guint8 channel, gpointer user_data); +/** + * GstRTSPKeepAliveFunc: + * @user_data: user data + * + * Function registered with gst_rtsp_stream_transport_set_keepalive() and called + * when the stream is active. + */ +typedef void (*GstRTSPKeepAliveFunc) (gpointer user_data); + +/** + * GstRTSPStreamTransport: + * @parent: parent instance + * + * A Transport description for a stream + */ +struct _GstRTSPStreamTransport { + GObject parent; + + /*< private >*/ + GstRTSPStreamTransportPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstRTSPStreamTransportClass { + GObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_rtsp_stream_transport_get_type (void); + +GstRTSPStreamTransport * gst_rtsp_stream_transport_new (GstRTSPStream *stream, + GstRTSPTransport *tr); + +GstRTSPStream * gst_rtsp_stream_transport_get_stream (GstRTSPStreamTransport *trans); + +void gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport *trans, + GstRTSPTransport * tr); +const GstRTSPTransport * gst_rtsp_stream_transport_get_transport (GstRTSPStreamTransport *trans); + +void gst_rtsp_stream_transport_set_url (GstRTSPStreamTransport *trans, + const GstRTSPUrl * url); +const GstRTSPUrl * gst_rtsp_stream_transport_get_url (GstRTSPStreamTransport *trans); + + +gchar * gst_rtsp_stream_transport_get_rtpinfo (GstRTSPStreamTransport *trans, + GstClockTime start_time); + +void gst_rtsp_stream_transport_set_callbacks (GstRTSPStreamTransport *trans, + GstRTSPSendFunc send_rtp, + GstRTSPSendFunc send_rtcp, + gpointer user_data, + GDestroyNotify notify); +void gst_rtsp_stream_transport_set_keepalive (GstRTSPStreamTransport *trans, + GstRTSPKeepAliveFunc keep_alive, + gpointer user_data, + GDestroyNotify notify); +void gst_rtsp_stream_transport_keep_alive (GstRTSPStreamTransport *trans); + +gboolean gst_rtsp_stream_transport_set_active (GstRTSPStreamTransport *trans, + gboolean active); + +void gst_rtsp_stream_transport_set_timed_out (GstRTSPStreamTransport *trans, + gboolean timedout); +gboolean gst_rtsp_stream_transport_is_timed_out (GstRTSPStreamTransport *trans); + + + +gboolean gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport *trans, + GstBuffer *buffer); +gboolean gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport *trans, + GstBuffer *buffer); + +G_END_DECLS + +#endif /* __GST_RTSP_STREAM_TRANSPORT_H__ */ diff --git a/gst/rtsp-server/rtsp-stream.c b/gst/rtsp-server/rtsp-stream.c new file mode 100644 index 0000000..8e1b216 --- /dev/null +++ b/gst/rtsp-server/rtsp-stream.c @@ -0,0 +1,2799 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-stream + * @short_description: A media stream + * @see_also: #GstRTSPMedia + * + * The #GstRTSPStream object manages the data transport for one stream. It + * is created from a payloader element and a source pad that produce the RTP + * packets for the stream. + * + * With gst_rtsp_stream_join_bin() the streaming elements are added to the bin + * and rtpbin. gst_rtsp_stream_leave_bin() removes the elements again. + * + * The #GstRTSPStream will use the configured addresspool, as set with + * gst_rtsp_stream_set_address_pool(), to allocate multicast addresses for the + * stream. With gst_rtsp_stream_get_multicast_address() you can get the + * configured address. + * + * With gst_rtsp_stream_get_server_port () you can get the port that the server + * will use to receive RTCP. This is the part that the clients will use to send + * RTCP to. + * + * With gst_rtsp_stream_add_transport() destinations can be added where the + * stream should be sent to. Use gst_rtsp_stream_remove_transport() to remove + * the destination again. + * + * Last reviewed on 2013-07-16 (1.0.0) + */ + +#include +#include +#include + +#include + +#include +#include + +#include "rtsp-stream.h" + +#define GST_RTSP_STREAM_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_STREAM, GstRTSPStreamPrivate)) + +struct _GstRTSPStreamPrivate +{ + GMutex lock; + guint idx; + GstPad *srcpad; + GstElement *payloader; + guint buffer_size; + gboolean is_joined; + gchar *control; + + GstRTSPProfile profiles; + GstRTSPLowerTrans protocols; + + /* pads on the rtpbin */ + GstPad *send_rtp_sink; + GstPad *recv_sink[2]; + GstPad *send_src[2]; + + /* the RTPSession object */ + GObject *session; + + /* SRTP encoder/decoder */ + GstElement *srtpenc; + GstElement *srtpdec; + GHashTable *keys; + + /* sinks used for sending and receiving RTP and RTCP over ipv4, they share + * sockets */ + GstElement *udpsrc_v4[2]; + + /* sinks used for sending and receiving RTP and RTCP over ipv6, they share + * sockets */ + GstElement *udpsrc_v6[2]; + + GstElement *udpsink[2]; + + /* for TCP transport */ + GstElement *appsrc[2]; + GstElement *appqueue[2]; + GstElement *appsink[2]; + + GstElement *tee[2]; + GstElement *funnel[2]; + + /* server ports for sending/receiving over ipv4 */ + GstRTSPRange server_port_v4; + GstRTSPAddress *server_addr_v4; + gboolean have_ipv4; + + /* server ports for sending/receiving over ipv6 */ + GstRTSPRange server_port_v6; + GstRTSPAddress *server_addr_v6; + gboolean have_ipv6; + + /* multicast addresses */ + GstRTSPAddressPool *pool; + GstRTSPAddress *addr_v4; + GstRTSPAddress *addr_v6; + + /* the caps of the stream */ + gulong caps_sig; + GstCaps *caps; + + /* transports we stream to */ + guint n_active; + GList *transports; + guint transports_cookie; + GList *tr_cache; + guint tr_cache_cookie; + + gint dscp_qos; + + /* stream blocking */ + gulong blocked_id; + gboolean blocking; +}; + +#define DEFAULT_CONTROL NULL +#define DEFAULT_PROFILES GST_RTSP_PROFILE_AVP +#define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \ + GST_RTSP_LOWER_TRANS_TCP + +enum +{ + PROP_0, + PROP_CONTROL, + PROP_PROFILES, + PROP_PROTOCOLS, + PROP_LAST +}; + +enum +{ + SIGNAL_NEW_RTP_ENCODER, + SIGNAL_NEW_RTCP_ENCODER, + SIGNAL_RTCP_STATS, + SIGNAL_LAST +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_stream_debug); +#define GST_CAT_DEFAULT rtsp_stream_debug + +static GQuark ssrc_stream_map_key; + +static void gst_rtsp_stream_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_stream_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); + +static void gst_rtsp_stream_finalize (GObject * obj); + +static guint gst_rtsp_stream_signals[SIGNAL_LAST] = { 0 }; + +G_DEFINE_TYPE (GstRTSPStream, gst_rtsp_stream, G_TYPE_OBJECT); + +static void +gst_rtsp_stream_class_init (GstRTSPStreamClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPStreamPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gst_rtsp_stream_get_property; + gobject_class->set_property = gst_rtsp_stream_set_property; + gobject_class->finalize = gst_rtsp_stream_finalize; + + g_object_class_install_property (gobject_class, PROP_CONTROL, + g_param_spec_string ("control", "Control", + "The control string for this stream", DEFAULT_CONTROL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_PROFILES, + g_param_spec_flags ("profiles", "Profiles", + "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE, + DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_PROTOCOLS, + g_param_spec_flags ("protocols", "Protocols", + "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS, + DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_rtsp_stream_signals[SIGNAL_NEW_RTP_ENCODER] = + g_signal_new ("new-rtp-encoder", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_ELEMENT); + + gst_rtsp_stream_signals[SIGNAL_NEW_RTCP_ENCODER] = + g_signal_new ("new-rtcp-encoder", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_ELEMENT); + + gst_rtsp_stream_signals[SIGNAL_RTCP_STATS] = + g_signal_new ("rtcp-statistics", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_STRUCTURE); + + GST_DEBUG_CATEGORY_INIT (rtsp_stream_debug, "rtspstream", 0, "GstRTSPStream"); + + ssrc_stream_map_key = g_quark_from_static_string ("GstRTSPServer.stream"); +} + +static void +gst_rtsp_stream_init (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv = GST_RTSP_STREAM_GET_PRIVATE (stream); + + GST_DEBUG ("new stream %p", stream); + + stream->priv = priv; + + priv->dscp_qos = -1; + priv->control = g_strdup (DEFAULT_CONTROL); + priv->profiles = DEFAULT_PROFILES; + priv->protocols = DEFAULT_PROTOCOLS; + + g_mutex_init (&priv->lock); + + priv->keys = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) gst_caps_unref); +} + +static void +gst_rtsp_stream_finalize (GObject * obj) +{ + GstRTSPStream *stream; + GstRTSPStreamPrivate *priv; + + stream = GST_RTSP_STREAM (obj); + priv = stream->priv; + + GST_DEBUG ("finalize stream %p", stream); + + /* we really need to be unjoined now */ + g_return_if_fail (!priv->is_joined); + + if (priv->addr_v4) + gst_rtsp_address_free (priv->addr_v4); + if (priv->addr_v6) + gst_rtsp_address_free (priv->addr_v6); + if (priv->server_addr_v4) + gst_rtsp_address_free (priv->server_addr_v4); + if (priv->server_addr_v6) + gst_rtsp_address_free (priv->server_addr_v6); + if (priv->pool) + g_object_unref (priv->pool); + gst_object_unref (priv->payloader); + gst_object_unref (priv->srcpad); + g_free (priv->control); + g_mutex_clear (&priv->lock); + + g_hash_table_unref (priv->keys); + + G_OBJECT_CLASS (gst_rtsp_stream_parent_class)->finalize (obj); +} + +static void +gst_rtsp_stream_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + GstRTSPStream *stream = GST_RTSP_STREAM (object); + + switch (propid) { + case PROP_CONTROL: + g_value_take_string (value, gst_rtsp_stream_get_control (stream)); + break; + case PROP_PROFILES: + g_value_set_flags (value, gst_rtsp_stream_get_profiles (stream)); + break; + case PROP_PROTOCOLS: + g_value_set_flags (value, gst_rtsp_stream_get_protocols (stream)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_stream_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + GstRTSPStream *stream = GST_RTSP_STREAM (object); + + switch (propid) { + case PROP_CONTROL: + gst_rtsp_stream_set_control (stream, g_value_get_string (value)); + break; + case PROP_PROFILES: + gst_rtsp_stream_set_profiles (stream, g_value_get_flags (value)); + break; + case PROP_PROTOCOLS: + gst_rtsp_stream_set_protocols (stream, g_value_get_flags (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +/** + * gst_rtsp_stream_new: + * @idx: an index + * @srcpad: a #GstPad + * @payloader: a #GstElement + * + * Create a new media stream with index @idx that handles RTP data on + * @srcpad and has a payloader element @payloader. + * + * Returns: (transfer full): a new #GstRTSPStream + */ +GstRTSPStream * +gst_rtsp_stream_new (guint idx, GstElement * payloader, GstPad * srcpad) +{ + GstRTSPStreamPrivate *priv; + GstRTSPStream *stream; + + g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL); + g_return_val_if_fail (GST_IS_PAD (srcpad), NULL); + g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), NULL); + + stream = g_object_new (GST_TYPE_RTSP_STREAM, NULL); + priv = stream->priv; + priv->idx = idx; + priv->payloader = gst_object_ref (payloader); + priv->srcpad = gst_object_ref (srcpad); + + return stream; +} + +/** + * gst_rtsp_stream_get_index: + * @stream: a #GstRTSPStream + * + * Get the stream index. + * + * Return: the stream index. + */ +guint +gst_rtsp_stream_get_index (GstRTSPStream * stream) +{ + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), -1); + + return stream->priv->idx; +} + +/** + * gst_rtsp_stream_get_pt: + * @stream: a #GstRTSPStream + * + * Get the stream payload type. + * + * Return: the stream payload type. + */ +guint +gst_rtsp_stream_get_pt (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + guint pt; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), -1); + + priv = stream->priv; + + g_object_get (G_OBJECT (priv->payloader), "pt", &pt, NULL); + + return pt; +} + +/** + * gst_rtsp_stream_get_srcpad: + * @stream: a #GstRTSPStream + * + * Get the srcpad associated with @stream. + * + * Returns: (transfer full): the srcpad. Unref after usage. + */ +GstPad * +gst_rtsp_stream_get_srcpad (GstRTSPStream * stream) +{ + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + + return gst_object_ref (stream->priv->srcpad); +} + +/** + * gst_rtsp_stream_get_control: + * @stream: a #GstRTSPStream + * + * Get the control string to identify this stream. + * + * Returns: (transfer full): the control string. g_free() after usage. + */ +gchar * +gst_rtsp_stream_get_control (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + gchar *result; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if ((result = g_strdup (priv->control)) == NULL) + result = g_strdup_printf ("stream=%u", priv->idx); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_stream_set_control: + * @stream: a #GstRTSPStream + * @control: a control string + * + * Set the control string in @stream. + */ +void +gst_rtsp_stream_set_control (GstRTSPStream * stream, const gchar * control) +{ + GstRTSPStreamPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + g_free (priv->control); + priv->control = g_strdup (control); + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_stream_has_control: + * @stream: a #GstRTSPStream + * @control: a control string + * + * Check if @stream has the control string @control. + * + * Returns: %TRUE is @stream has @control as the control string + */ +gboolean +gst_rtsp_stream_has_control (GstRTSPStream * stream, const gchar * control) +{ + GstRTSPStreamPrivate *priv; + gboolean res; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if (priv->control) + res = (g_strcmp0 (priv->control, control) == 0); + else { + guint streamid; + + if (sscanf (control, "stream=%u", &streamid) > 0) + res = (streamid == priv->idx); + else + res = FALSE; + } + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_stream_set_mtu: + * @stream: a #GstRTSPStream + * @mtu: a new MTU + * + * Configure the mtu in the payloader of @stream to @mtu. + */ +void +gst_rtsp_stream_set_mtu (GstRTSPStream * stream, guint mtu) +{ + GstRTSPStreamPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + + priv = stream->priv; + + GST_LOG_OBJECT (stream, "set MTU %u", mtu); + + g_object_set (G_OBJECT (priv->payloader), "mtu", mtu, NULL); +} + +/** + * gst_rtsp_stream_get_mtu: + * @stream: a #GstRTSPStream + * + * Get the configured MTU in the payloader of @stream. + * + * Returns: the MTU of the payloader. + */ +guint +gst_rtsp_stream_get_mtu (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + guint mtu; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), 0); + + priv = stream->priv; + + g_object_get (G_OBJECT (priv->payloader), "mtu", &mtu, NULL); + + return mtu; +} + +/* Update the dscp qos property on the udp sinks */ +static void +update_dscp_qos (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + + priv = stream->priv; + + if (priv->udpsink[0]) { + g_object_set (G_OBJECT (priv->udpsink[0]), "qos-dscp", priv->dscp_qos, + NULL); + } + + if (priv->udpsink[1]) { + g_object_set (G_OBJECT (priv->udpsink[1]), "qos-dscp", priv->dscp_qos, + NULL); + } +} + +/** + * gst_rtsp_stream_set_dscp_qos: + * @stream: a #GstRTSPStream + * @dscp_qos: a new dscp qos value (0-63, or -1 to disable) + * + * Configure the dscp qos of the outgoing sockets to @dscp_qos. + */ +void +gst_rtsp_stream_set_dscp_qos (GstRTSPStream * stream, gint dscp_qos) +{ + GstRTSPStreamPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + + priv = stream->priv; + + GST_LOG_OBJECT (stream, "set DSCP QoS %d", dscp_qos); + + if (dscp_qos < -1 || dscp_qos > 63) { + GST_WARNING_OBJECT (stream, "trying to set illegal dscp qos %d", dscp_qos); + return; + } + + priv->dscp_qos = dscp_qos; + + update_dscp_qos (stream); +} + +/** + * gst_rtsp_stream_get_dscp_qos: + * @stream: a #GstRTSPStream + * + * Get the configured DSCP QoS in of the outgoing sockets. + * + * Returns: the DSCP QoS value of the outgoing sockets, or -1 if disbled. + */ +gint +gst_rtsp_stream_get_dscp_qos (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), -1); + + priv = stream->priv; + + return priv->dscp_qos; +} + +/** + * gst_rtsp_stream_is_transport_supported: + * @stream: a #GstRTSPStream + * @transport: (transfer none): a #GstRTSPTransport + * + * Check if @transport can be handled by stream + * + * Returns: %TRUE if @transport can be handled by @stream. + */ +gboolean +gst_rtsp_stream_is_transport_supported (GstRTSPStream * stream, + GstRTSPTransport * transport) +{ + GstRTSPStreamPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if (transport->trans != GST_RTSP_TRANS_RTP) + goto unsupported_transmode; + + if (!(transport->profile & priv->profiles)) + goto unsupported_profile; + + if (!(transport->lower_transport & priv->protocols)) + goto unsupported_ltrans; + + g_mutex_unlock (&priv->lock); + + return TRUE; + + /* ERRORS */ +unsupported_transmode: + { + GST_DEBUG ("unsupported transport mode %d", transport->trans); + g_mutex_unlock (&priv->lock); + return FALSE; + } +unsupported_profile: + { + GST_DEBUG ("unsupported profile %d", transport->profile); + g_mutex_unlock (&priv->lock); + return FALSE; + } +unsupported_ltrans: + { + GST_DEBUG ("unsupported lower transport %d", transport->lower_transport); + g_mutex_unlock (&priv->lock); + return FALSE; + } +} + +/** + * gst_rtsp_stream_set_profiles: + * @stream: a #GstRTSPStream + * @profiles: the new profiles + * + * Configure the allowed profiles for @stream. + */ +void +gst_rtsp_stream_set_profiles (GstRTSPStream * stream, GstRTSPProfile profiles) +{ + GstRTSPStreamPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + priv->profiles = profiles; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_stream_get_profiles: + * @stream: a #GstRTSPStream + * + * Get the allowed profiles of @stream. + * + * Returns: a #GstRTSPProfile + */ +GstRTSPProfile +gst_rtsp_stream_get_profiles (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + GstRTSPProfile res; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), GST_RTSP_PROFILE_UNKNOWN); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + res = priv->profiles; + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_stream_set_protocols: + * @stream: a #GstRTSPStream + * @protocols: the new flags + * + * Configure the allowed lower transport for @stream. + */ +void +gst_rtsp_stream_set_protocols (GstRTSPStream * stream, + GstRTSPLowerTrans protocols) +{ + GstRTSPStreamPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + priv->protocols = protocols; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_stream_get_protocols: + * @stream: a #GstRTSPStream + * + * Get the allowed protocols of @stream. + * + * Returns: a #GstRTSPLowerTrans + */ +GstRTSPLowerTrans +gst_rtsp_stream_get_protocols (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + GstRTSPLowerTrans res; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), + GST_RTSP_LOWER_TRANS_UNKNOWN); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + res = priv->protocols; + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_stream_set_address_pool: + * @stream: a #GstRTSPStream + * @pool: (transfer none): a #GstRTSPAddressPool + * + * configure @pool to be used as the address pool of @stream. + */ +void +gst_rtsp_stream_set_address_pool (GstRTSPStream * stream, + GstRTSPAddressPool * pool) +{ + GstRTSPStreamPrivate *priv; + GstRTSPAddressPool *old; + + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + + priv = stream->priv; + + GST_LOG_OBJECT (stream, "set address pool %p", pool); + + g_mutex_lock (&priv->lock); + if ((old = priv->pool) != pool) + priv->pool = pool ? g_object_ref (pool) : NULL; + else + old = NULL; + g_mutex_unlock (&priv->lock); + + if (old) + g_object_unref (old); +} + +/** + * gst_rtsp_stream_get_address_pool: + * @stream: a #GstRTSPStream + * + * Get the #GstRTSPAddressPool used as the address pool of @stream. + * + * Returns: (transfer full): the #GstRTSPAddressPool of @stream. g_object_unref() after + * usage. + */ +GstRTSPAddressPool * +gst_rtsp_stream_get_address_pool (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + GstRTSPAddressPool *result; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if ((result = priv->pool)) + g_object_ref (result); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_stream_get_multicast_address: + * @stream: a #GstRTSPStream + * @family: the #GSocketFamily + * + * Get the multicast address of @stream for @family. + * + * Returns: (transfer full) (nullable): the #GstRTSPAddress of @stream + * or %NULL when no address could be allocated. gst_rtsp_address_free() + * after usage. + */ +GstRTSPAddress * +gst_rtsp_stream_get_multicast_address (GstRTSPStream * stream, + GSocketFamily family) +{ + GstRTSPStreamPrivate *priv; + GstRTSPAddress *result; + GstRTSPAddress **addrp; + GstRTSPAddressFlags flags; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + + priv = stream->priv; + + if (family == G_SOCKET_FAMILY_IPV6) { + flags = GST_RTSP_ADDRESS_FLAG_IPV6; + addrp = &priv->addr_v6; + } else { + flags = GST_RTSP_ADDRESS_FLAG_IPV4; + addrp = &priv->addr_v4; + } + + g_mutex_lock (&priv->lock); + if (*addrp == NULL) { + if (priv->pool == NULL) + goto no_pool; + + flags |= GST_RTSP_ADDRESS_FLAG_EVEN_PORT | GST_RTSP_ADDRESS_FLAG_MULTICAST; + + *addrp = gst_rtsp_address_pool_acquire_address (priv->pool, flags, 2); + if (*addrp == NULL) + goto no_address; + } + result = gst_rtsp_address_copy (*addrp); + g_mutex_unlock (&priv->lock); + + return result; + + /* ERRORS */ +no_pool: + { + GST_ERROR_OBJECT (stream, "no address pool specified"); + g_mutex_unlock (&priv->lock); + return NULL; + } +no_address: + { + GST_ERROR_OBJECT (stream, "failed to acquire address from pool"); + g_mutex_unlock (&priv->lock); + return NULL; + } +} + +/** + * gst_rtsp_stream_reserve_address: + * @stream: a #GstRTSPStream + * @address: an address + * @port: a port + * @n_ports: n_ports + * @ttl: a TTL + * + * Reserve @address and @port as the address and port of @stream. + * + * Returns: (nullable): the #GstRTSPAddress of @stream or %NULL when + * the address could be reserved. gst_rtsp_address_free() after usage. + */ +GstRTSPAddress * +gst_rtsp_stream_reserve_address (GstRTSPStream * stream, + const gchar * address, guint port, guint n_ports, guint ttl) +{ + GstRTSPStreamPrivate *priv; + GstRTSPAddress *result; + GInetAddress *addr; + GSocketFamily family; + GstRTSPAddress **addrp; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + g_return_val_if_fail (address != NULL, NULL); + g_return_val_if_fail (port > 0, NULL); + g_return_val_if_fail (n_ports > 0, NULL); + g_return_val_if_fail (ttl > 0, NULL); + + priv = stream->priv; + + addr = g_inet_address_new_from_string (address); + if (!addr) { + GST_ERROR ("failed to get inet addr from %s", address); + family = G_SOCKET_FAMILY_IPV4; + } else { + family = g_inet_address_get_family (addr); + g_object_unref (addr); + } + + if (family == G_SOCKET_FAMILY_IPV6) + addrp = &priv->addr_v6; + else + addrp = &priv->addr_v4; + + g_mutex_lock (&priv->lock); + if (*addrp == NULL) { + GstRTSPAddressPoolResult res; + + if (priv->pool == NULL) + goto no_pool; + + res = gst_rtsp_address_pool_reserve_address (priv->pool, address, + port, n_ports, ttl, addrp); + if (res != GST_RTSP_ADDRESS_POOL_OK) + goto no_address; + } else { + if (strcmp ((*addrp)->address, address) || + (*addrp)->port != port || (*addrp)->n_ports != n_ports || + (*addrp)->ttl != ttl) + goto different_address; + } + result = gst_rtsp_address_copy (*addrp); + g_mutex_unlock (&priv->lock); + + return result; + + /* ERRORS */ +no_pool: + { + GST_ERROR_OBJECT (stream, "no address pool specified"); + g_mutex_unlock (&priv->lock); + return NULL; + } +no_address: + { + GST_ERROR_OBJECT (stream, "failed to acquire address %s from pool", + address); + g_mutex_unlock (&priv->lock); + return NULL; + } +different_address: + { + GST_ERROR_OBJECT (stream, "address %s is not the same that was already" + " reserved", address); + g_mutex_unlock (&priv->lock); + return NULL; + } +} + +static gboolean +alloc_ports_one_family (GstRTSPAddressPool * pool, gint buffer_size, + GSocketFamily family, GstElement * udpsrc_out[2], + GstElement * udpsink_out[2], GstRTSPRange * server_port_out, + GstRTSPAddress ** server_addr_out) +{ + GstStateChangeReturn ret; + GstElement *udpsrc0, *udpsrc1; + GstElement *udpsink0, *udpsink1; + GSocket *rtp_socket = NULL; + GSocket *rtcp_socket; + gint tmp_rtp, tmp_rtcp; + guint count; + gint rtpport, rtcpport; + GList *rejected_addresses = NULL; + GstRTSPAddress *addr = NULL; + GInetAddress *inetaddr = NULL; + GSocketAddress *rtp_sockaddr = NULL; + GSocketAddress *rtcp_sockaddr = NULL; + const gchar *multisink_socket; + + if (family == G_SOCKET_FAMILY_IPV6) + multisink_socket = "socket-v6"; + else + multisink_socket = "socket"; + + udpsrc0 = NULL; + udpsrc1 = NULL; + udpsink0 = NULL; + udpsink1 = NULL; + count = 0; + + /* Start with random port */ + tmp_rtp = 0; + + rtcp_socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, + G_SOCKET_PROTOCOL_UDP, NULL); + if (!rtcp_socket) + goto no_udp_protocol; + + if (*server_addr_out) + gst_rtsp_address_free (*server_addr_out); + + /* try to allocate 2 UDP ports, the RTP port should be an even + * number and the RTCP port should be the next (uneven) port */ +again: + + if (rtp_socket == NULL) { + rtp_socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, + G_SOCKET_PROTOCOL_UDP, NULL); + if (!rtp_socket) + goto no_udp_protocol; + } + + if (pool && gst_rtsp_address_pool_has_unicast_addresses (pool)) { + GstRTSPAddressFlags flags; + + if (addr) + rejected_addresses = g_list_prepend (rejected_addresses, addr); + + flags = GST_RTSP_ADDRESS_FLAG_EVEN_PORT | GST_RTSP_ADDRESS_FLAG_UNICAST; + if (family == G_SOCKET_FAMILY_IPV6) + flags |= GST_RTSP_ADDRESS_FLAG_IPV6; + else + flags |= GST_RTSP_ADDRESS_FLAG_IPV4; + + addr = gst_rtsp_address_pool_acquire_address (pool, flags, 2); + + if (addr == NULL) + goto no_ports; + + tmp_rtp = addr->port; + + g_clear_object (&inetaddr); + inetaddr = g_inet_address_new_from_string (addr->address); + } else { + if (tmp_rtp != 0) { + tmp_rtp += 2; + if (++count > 20) + goto no_ports; + } + + if (inetaddr == NULL) + inetaddr = g_inet_address_new_any (family); + } + + /* FIXME-WFD : Force to set 19000 as port number */ + tmp_rtp = 19000; + + rtp_sockaddr = g_inet_socket_address_new (inetaddr, tmp_rtp); + if (!g_socket_bind (rtp_socket, rtp_sockaddr, FALSE, NULL)) { + g_object_unref (rtp_sockaddr); + goto again; + } + g_object_unref (rtp_sockaddr); + + rtp_sockaddr = g_socket_get_local_address (rtp_socket, NULL); + if (rtp_sockaddr == NULL || !G_IS_INET_SOCKET_ADDRESS (rtp_sockaddr)) { + g_clear_object (&rtp_sockaddr); + goto socket_error; + } + + tmp_rtp = + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (rtp_sockaddr)); + g_object_unref (rtp_sockaddr); + + /* check if port is even */ + if ((tmp_rtp & 1) != 0) { + /* port not even, close and allocate another */ + tmp_rtp++; + g_clear_object (&rtp_socket); + goto again; + } + + /* set port */ + tmp_rtcp = tmp_rtp + 1; + + rtcp_sockaddr = g_inet_socket_address_new (inetaddr, tmp_rtcp); + if (!g_socket_bind (rtcp_socket, rtcp_sockaddr, FALSE, NULL)) { + g_object_unref (rtcp_sockaddr); + g_clear_object (&rtp_socket); + goto again; + } + g_object_unref (rtcp_sockaddr); + + g_clear_object (&inetaddr); + + udpsrc0 = gst_element_factory_make ("udpsrc", NULL); + udpsrc1 = gst_element_factory_make ("udpsrc", NULL); + + if (udpsrc0 == NULL || udpsrc1 == NULL) + goto no_udp_protocol; + + g_object_set (G_OBJECT (udpsrc0), "socket", rtp_socket, NULL); + g_object_set (G_OBJECT (udpsrc1), "socket", rtcp_socket, NULL); + + ret = gst_element_set_state (udpsrc0, GST_STATE_READY); + if (ret == GST_STATE_CHANGE_FAILURE) + goto element_error; + ret = gst_element_set_state (udpsrc1, GST_STATE_READY); + if (ret == GST_STATE_CHANGE_FAILURE) + goto element_error; + + /* all fine, do port check */ + g_object_get (G_OBJECT (udpsrc0), "port", &rtpport, NULL); + g_object_get (G_OBJECT (udpsrc1), "port", &rtcpport, NULL); + + /* this should not happen... */ + if (rtpport != tmp_rtp || rtcpport != tmp_rtcp) + goto port_error; + + if (udpsink_out[0]) + udpsink0 = udpsink_out[0]; + else + udpsink0 = gst_element_factory_make ("multiudpsink", NULL); + + if (!udpsink0) + goto no_udp_protocol; + + g_object_set (G_OBJECT (udpsink0), "close-socket", FALSE, NULL); + g_object_set (G_OBJECT (udpsink0), multisink_socket, rtp_socket, NULL); + + if (udpsink_out[1]) + udpsink1 = udpsink_out[1]; + else + udpsink1 = gst_element_factory_make ("multiudpsink", NULL); + + if (!udpsink1) + goto no_udp_protocol; + + g_object_set (G_OBJECT (udpsink0), "send-duplicates", FALSE, NULL); + g_object_set (G_OBJECT (udpsink1), "send-duplicates", FALSE, NULL); + g_object_set (G_OBJECT (udpsink0), "buffer-size", buffer_size, NULL); + + g_object_set (G_OBJECT (udpsink1), "close-socket", FALSE, NULL); + g_object_set (G_OBJECT (udpsink1), multisink_socket, rtcp_socket, NULL); + g_object_set (G_OBJECT (udpsink1), "sync", FALSE, NULL); + g_object_set (G_OBJECT (udpsink1), "async", FALSE, NULL); + g_object_set (G_OBJECT (udpsink0), "auto-multicast", FALSE, NULL); + g_object_set (G_OBJECT (udpsink0), "loop", FALSE, NULL); + g_object_set (G_OBJECT (udpsink1), "auto-multicast", FALSE, NULL); + g_object_set (G_OBJECT (udpsink1), "loop", FALSE, NULL); + + /* we keep these elements, we will further configure them when the + * client told us to really use the UDP ports. */ + udpsrc_out[0] = udpsrc0; + udpsrc_out[1] = udpsrc1; + udpsink_out[0] = udpsink0; + udpsink_out[1] = udpsink1; + server_port_out->min = rtpport; + server_port_out->max = rtcpport; + + *server_addr_out = addr; + g_list_free_full (rejected_addresses, (GDestroyNotify) gst_rtsp_address_free); + + g_object_unref (rtp_socket); + g_object_unref (rtcp_socket); + + return TRUE; + + /* ERRORS */ +no_udp_protocol: + { + goto cleanup; + } +no_ports: + { + goto cleanup; + } +port_error: + { + goto cleanup; + } +socket_error: + { + goto cleanup; + } +element_error: + { + goto cleanup; + } +cleanup: + { + if (udpsrc0) { + gst_element_set_state (udpsrc0, GST_STATE_NULL); + gst_object_unref (udpsrc0); + } + if (udpsrc1) { + gst_element_set_state (udpsrc1, GST_STATE_NULL); + gst_object_unref (udpsrc1); + } + if (udpsink0) { + gst_element_set_state (udpsink0, GST_STATE_NULL); + gst_object_unref (udpsink0); + } + if (inetaddr) + g_object_unref (inetaddr); + g_list_free_full (rejected_addresses, + (GDestroyNotify) gst_rtsp_address_free); + if (addr) + gst_rtsp_address_free (addr); + if (rtp_socket) + g_object_unref (rtp_socket); + if (rtcp_socket) + g_object_unref (rtcp_socket); + return FALSE; + } +} + +/* must be called with lock */ +static gboolean +alloc_ports (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv = stream->priv; + + priv->have_ipv4 = alloc_ports_one_family (priv->pool, priv->buffer_size, + G_SOCKET_FAMILY_IPV4, priv->udpsrc_v4, priv->udpsink, + &priv->server_port_v4, &priv->server_addr_v4); + + /* FIXME-WFD : force to disable ipv6 mode in WFD mode */ +#if 0 + priv->have_ipv6 = alloc_ports_one_family (priv->pool, priv->buffer_size, + G_SOCKET_FAMILY_IPV6, priv->udpsrc_v6, priv->udpsink, + &priv->server_port_v6, &priv->server_addr_v6); +#else + priv->have_ipv6 = FALSE; +#endif + + return priv->have_ipv4 || priv->have_ipv6; +} + +/** + * gst_rtsp_stream_get_server_port: + * @stream: a #GstRTSPStream + * @server_port: (out): result server port + * @family: the port family to get + * + * Fill @server_port with the port pair used by the server. This function can + * only be called when @stream has been joined. + */ +void +gst_rtsp_stream_get_server_port (GstRTSPStream * stream, + GstRTSPRange * server_port, GSocketFamily family) +{ + GstRTSPStreamPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + priv = stream->priv; + g_return_if_fail (priv->is_joined); + + g_mutex_lock (&priv->lock); + if (family == G_SOCKET_FAMILY_IPV4) { + if (server_port) + *server_port = priv->server_port_v4; + } else { + if (server_port) + *server_port = priv->server_port_v6; + } + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_stream_get_rtpsession: + * @stream: a #GstRTSPStream + * + * Get the RTP session of this stream. + * + * Returns: (transfer full): The RTP session of this stream. Unref after usage. + */ +GObject * +gst_rtsp_stream_get_rtpsession (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + GObject *session; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if ((session = priv->session)) + g_object_ref (session); + g_mutex_unlock (&priv->lock); + + return session; +} + +/** + * gst_rtsp_stream_get_ssrc: + * @stream: a #GstRTSPStream + * @ssrc: (out): result ssrc + * + * Get the SSRC used by the RTP session of this stream. This function can only + * be called when @stream has been joined. + */ +void +gst_rtsp_stream_get_ssrc (GstRTSPStream * stream, guint * ssrc) +{ + GstRTSPStreamPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + priv = stream->priv; + g_return_if_fail (priv->is_joined); + + g_mutex_lock (&priv->lock); + if (ssrc && priv->session) + g_object_get (priv->session, "internal-ssrc", ssrc, NULL); + g_mutex_unlock (&priv->lock); +} + +/* executed from streaming thread */ +static void +caps_notify (GstPad * pad, GParamSpec * unused, GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv = stream->priv; + GstCaps *newcaps, *oldcaps; + + newcaps = gst_pad_get_current_caps (pad); + + GST_INFO ("stream %p received caps %p, %" GST_PTR_FORMAT, stream, newcaps, + newcaps); + + g_mutex_lock (&priv->lock); + oldcaps = priv->caps; + priv->caps = newcaps; + g_mutex_unlock (&priv->lock); + + if (oldcaps) + gst_caps_unref (oldcaps); +} + +static void +dump_structure (const GstStructure * s) +{ + gchar *sstr; + + sstr = gst_structure_to_string (s); + GST_INFO ("structure: %s", sstr); + g_free (sstr); +} + +static GstRTSPStreamTransport * +find_transport (GstRTSPStream * stream, const gchar * rtcp_from) +{ + GstRTSPStreamPrivate *priv = stream->priv; + GList *walk; + GstRTSPStreamTransport *result = NULL; + const gchar *tmp; + gchar *dest; + guint port; + + if (rtcp_from == NULL) + return NULL; + + tmp = g_strrstr (rtcp_from, ":"); + if (tmp == NULL) + return NULL; + + port = atoi (tmp + 1); + dest = g_strndup (rtcp_from, tmp - rtcp_from); + + g_mutex_lock (&priv->lock); + GST_INFO ("finding %s:%d in %d transports", dest, port, + g_list_length (priv->transports)); + + for (walk = priv->transports; walk; walk = g_list_next (walk)) { + GstRTSPStreamTransport *trans = walk->data; + const GstRTSPTransport *tr; + gint min, max; + + tr = gst_rtsp_stream_transport_get_transport (trans); + + min = tr->client_port.min; + max = tr->client_port.max; + + if ((strcmp (tr->destination, dest) == 0) && (min == port || max == port)) { + result = trans; + break; + } + } + if (result) + g_object_ref (result); + g_mutex_unlock (&priv->lock); + + g_free (dest); + + return result; +} + +static GstRTSPStreamTransport * +check_transport (GObject * source, GstRTSPStream * stream) +{ + GstStructure *stats; + GstRTSPStreamTransport *trans; + + /* see if we have a stream to match with the origin of the RTCP packet */ + trans = g_object_get_qdata (source, ssrc_stream_map_key); + if (trans == NULL) { + g_object_get (source, "stats", &stats, NULL); + if (stats) { + const gchar *rtcp_from; + + dump_structure (stats); + + g_signal_emit (stream, gst_rtsp_stream_signals[SIGNAL_RTCP_STATS], 0, stats); + + rtcp_from = gst_structure_get_string (stats, "rtcp-from"); + if ((trans = find_transport (stream, rtcp_from))) { + GST_INFO ("%p: found transport %p for source %p", stream, trans, + source); + g_object_set_qdata_full (source, ssrc_stream_map_key, trans, + g_object_unref); + } + gst_structure_free (stats); + } + } + return trans; +} + + +static void +on_new_ssrc (GObject * session, GObject * source, GstRTSPStream * stream) +{ + GstRTSPStreamTransport *trans; + + GST_INFO ("%p: new source %p", stream, source); + + trans = check_transport (source, stream); + + if (trans) + GST_INFO ("%p: source %p for transport %p", stream, source, trans); +} + +static void +on_ssrc_sdes (GObject * session, GObject * source, GstRTSPStream * stream) +{ + GST_INFO ("%p: new SDES %p", stream, source); +} + +static void +on_ssrc_active (GObject * session, GObject * source, GstRTSPStream * stream) +{ + GstRTSPStreamTransport *trans; + + trans = check_transport (source, stream); + + if (trans) { + GST_INFO ("%p: source %p in transport %p is active", stream, source, trans); + gst_rtsp_stream_transport_keep_alive (trans); + } + { + GstStructure *stats; + g_object_get (source, "stats", &stats, NULL); + if (stats) { + g_signal_emit (stream, gst_rtsp_stream_signals[SIGNAL_RTCP_STATS], 0, stats); + +#ifdef DUMP_STATS + dump_structure (stats); +#endif + gst_structure_free (stats); + } + } +} + +static void +on_bye_ssrc (GObject * session, GObject * source, GstRTSPStream * stream) +{ + GST_INFO ("%p: source %p bye", stream, source); +} + +static void +on_bye_timeout (GObject * session, GObject * source, GstRTSPStream * stream) +{ + GstRTSPStreamTransport *trans; + + GST_INFO ("%p: source %p bye timeout", stream, source); + + if ((trans = g_object_get_qdata (source, ssrc_stream_map_key))) { + gst_rtsp_stream_transport_set_timed_out (trans, TRUE); + g_object_set_qdata (source, ssrc_stream_map_key, NULL); + } +} + +static void +on_timeout (GObject * session, GObject * source, GstRTSPStream * stream) +{ + GstRTSPStreamTransport *trans; + + GST_INFO ("%p: source %p timeout", stream, source); + + if ((trans = g_object_get_qdata (source, ssrc_stream_map_key))) { + gst_rtsp_stream_transport_set_timed_out (trans, TRUE); + g_object_set_qdata (source, ssrc_stream_map_key, NULL); + } +} + +static void +clear_tr_cache (GstRTSPStreamPrivate * priv) +{ + g_list_foreach (priv->tr_cache, (GFunc) g_object_unref, NULL); + g_list_free (priv->tr_cache); + priv->tr_cache = NULL; +} + +static GstFlowReturn +handle_new_sample (GstAppSink * sink, gpointer user_data) +{ + GstRTSPStreamPrivate *priv; + GList *walk; + GstSample *sample; + GstBuffer *buffer; + GstRTSPStream *stream; + gboolean is_rtp; + + sample = gst_app_sink_pull_sample (sink); + if (!sample) + return GST_FLOW_OK; + + stream = (GstRTSPStream *) user_data; + priv = stream->priv; + buffer = gst_sample_get_buffer (sample); + + is_rtp = GST_ELEMENT_CAST (sink) == priv->appsink[0]; + + g_mutex_lock (&priv->lock); + if (priv->tr_cache_cookie != priv->transports_cookie) { + clear_tr_cache (priv); + for (walk = priv->transports; walk; walk = g_list_next (walk)) { + GstRTSPStreamTransport *tr = (GstRTSPStreamTransport *) walk->data; + priv->tr_cache = g_list_prepend (priv->tr_cache, g_object_ref (tr)); + } + priv->tr_cache_cookie = priv->transports_cookie; + } + g_mutex_unlock (&priv->lock); + + for (walk = priv->tr_cache; walk; walk = g_list_next (walk)) { + GstRTSPStreamTransport *tr = (GstRTSPStreamTransport *) walk->data; + + if (is_rtp) { + gst_rtsp_stream_transport_send_rtp (tr, buffer); + } else { + gst_rtsp_stream_transport_send_rtcp (tr, buffer); + } + } + gst_sample_unref (sample); + + return GST_FLOW_OK; +} + +static GstAppSinkCallbacks sink_cb = { + NULL, /* not interested in EOS */ + NULL, /* not interested in preroll samples */ + handle_new_sample, +}; + +static GstElement * +get_rtp_encoder (GstRTSPStream * stream, guint session) +{ + GstRTSPStreamPrivate *priv = stream->priv; + + if (priv->srtpenc == NULL) { + gchar *name; + + name = g_strdup_printf ("srtpenc_%u", session); + priv->srtpenc = gst_element_factory_make ("srtpenc", name); + g_free (name); + + g_object_set (priv->srtpenc, "random-key", TRUE, NULL); + } + return gst_object_ref (priv->srtpenc); +} + +static GstElement * +request_rtp_encoder (GstElement * rtpbin, guint session, GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv = stream->priv; + GstElement *oldenc, *enc; + GstPad *pad; + gchar *name; + + if (priv->idx != session) + return NULL; + + GST_DEBUG_OBJECT (stream, "make RTP encoder for session %u", session); + + oldenc = priv->srtpenc; + enc = get_rtp_encoder (stream, session); + name = g_strdup_printf ("rtp_sink_%d", session); + pad = gst_element_get_request_pad (enc, name); + g_free (name); + gst_object_unref (pad); + + if (oldenc == NULL) + g_signal_emit (stream, gst_rtsp_stream_signals[SIGNAL_NEW_RTP_ENCODER], 0, + enc); + + return enc; +} + +static GstElement * +request_rtcp_encoder (GstElement * rtpbin, guint session, + GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv = stream->priv; + GstElement *oldenc, *enc; + GstPad *pad; + gchar *name; + + if (priv->idx != session) + return NULL; + + GST_DEBUG_OBJECT (stream, "make RTCP encoder for session %u", session); + + oldenc = priv->srtpenc; + enc = get_rtp_encoder (stream, session); + name = g_strdup_printf ("rtcp_sink_%d", session); + pad = gst_element_get_request_pad (enc, name); + g_free (name); + gst_object_unref (pad); + + if (oldenc == NULL) + g_signal_emit (stream, gst_rtsp_stream_signals[SIGNAL_NEW_RTCP_ENCODER], 0, + enc); + + return enc; +} + +static GstCaps * +request_key (GstElement * srtpdec, guint ssrc, GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv = stream->priv; + GstCaps *caps; + + GST_DEBUG ("request key %08x", ssrc); + + g_mutex_lock (&priv->lock); + if ((caps = g_hash_table_lookup (priv->keys, GINT_TO_POINTER (ssrc)))) + gst_caps_ref (caps); + g_mutex_unlock (&priv->lock); + + return caps; +} + +static GstElement * +request_rtcp_decoder (GstElement * rtpbin, guint session, + GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv = stream->priv; + + if (priv->idx != session) + return NULL; + + if (priv->srtpdec == NULL) { + gchar *name; + + name = g_strdup_printf ("srtpdec_%u", session); + priv->srtpdec = gst_element_factory_make ("srtpdec", name); + g_free (name); + + g_signal_connect (priv->srtpdec, "request-key", + (GCallback) request_key, stream); + } + return gst_object_ref (priv->srtpdec); +} + +/** + * gst_rtsp_stream_join_bin: + * @stream: a #GstRTSPStream + * @bin: (transfer none): a #GstBin to join + * @rtpbin: (transfer none): a rtpbin element in @bin + * @state: the target state of the new elements + * + * Join the #GstBin @bin that contains the element @rtpbin. + * + * @stream will link to @rtpbin, which must be inside @bin. The elements + * added to @bin will be set to the state given in @state. + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin, + GstElement * rtpbin, GstState state) +{ + GstRTSPStreamPrivate *priv; + gint i; + guint idx; + gchar *name; + GstPad *pad, *sinkpad, *selpad; + GstPadLinkReturn ret; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + g_return_val_if_fail (GST_IS_BIN (bin), FALSE); + g_return_val_if_fail (GST_IS_ELEMENT (rtpbin), FALSE); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if (priv->is_joined) + goto was_joined; + + /* create a session with the same index as the stream */ + idx = priv->idx; + + GST_INFO ("stream %p joining bin as session %u", stream, idx); + + if (!alloc_ports (stream)) + goto no_ports; + + /* update the dscp qos field in the sinks */ + update_dscp_qos (stream); + + if (priv->profiles & GST_RTSP_PROFILE_SAVP + || priv->profiles & GST_RTSP_PROFILE_SAVPF) { + /* For SRTP */ + g_signal_connect (rtpbin, "request-rtp-encoder", + (GCallback) request_rtp_encoder, stream); + g_signal_connect (rtpbin, "request-rtcp-encoder", + (GCallback) request_rtcp_encoder, stream); + g_signal_connect (rtpbin, "request-rtcp-decoder", + (GCallback) request_rtcp_decoder, stream); + } + + /* get a pad for sending RTP */ + name = g_strdup_printf ("send_rtp_sink_%u", idx); + priv->send_rtp_sink = gst_element_get_request_pad (rtpbin, name); + g_free (name); + /* link the RTP pad to the session manager, it should not really fail unless + * this is not really an RTP pad */ + ret = gst_pad_link (priv->srcpad, priv->send_rtp_sink); + if (ret != GST_PAD_LINK_OK) + goto link_failed; + + /* get pads from the RTP session element for sending and receiving + * RTP/RTCP*/ + name = g_strdup_printf ("send_rtp_src_%u", idx); + priv->send_src[0] = gst_element_get_static_pad (rtpbin, name); + g_free (name); + name = g_strdup_printf ("send_rtcp_src_%u", idx); + priv->send_src[1] = gst_element_get_request_pad (rtpbin, name); + g_free (name); + name = g_strdup_printf ("recv_rtp_sink_%u", idx); + priv->recv_sink[0] = gst_element_get_request_pad (rtpbin, name); + g_free (name); + name = g_strdup_printf ("recv_rtcp_sink_%u", idx); + priv->recv_sink[1] = gst_element_get_request_pad (rtpbin, name); + g_free (name); + + /* get the session */ + g_signal_emit_by_name (rtpbin, "get-internal-session", idx, &priv->session); + + g_signal_connect (priv->session, "on-new-ssrc", (GCallback) on_new_ssrc, + stream); + g_signal_connect (priv->session, "on-ssrc-sdes", (GCallback) on_ssrc_sdes, + stream); + g_signal_connect (priv->session, "on-ssrc-active", + (GCallback) on_ssrc_active, stream); + g_signal_connect (priv->session, "on-bye-ssrc", (GCallback) on_bye_ssrc, + stream); + g_signal_connect (priv->session, "on-bye-timeout", + (GCallback) on_bye_timeout, stream); + g_signal_connect (priv->session, "on-timeout", (GCallback) on_timeout, + stream); + + for (i = 0; i < 2; i++) { + GstPad *teepad, *queuepad; + /* For the sender we create this bit of pipeline for both + * RTP and RTCP. Sync and preroll are enabled on udpsink so + * we need to add a queue before appsink to make the pipeline + * not block. For the TCP case, we want to pump data to the + * client as fast as possible anyway. + * + * .--------. .-----. .---------. + * | rtpbin | | tee | | udpsink | + * | send->sink src->sink | + * '--------' | | '---------' + * | | .---------. .---------. + * | | | queue | | appsink | + * | src->sink src->sink | + * '-----' '---------' '---------' + * + * When only UDP is allowed, we skip the tee, queue and appsink and link the + * udpsink directly to the session. + */ + /* add udpsink */ + gst_bin_add (bin, priv->udpsink[i]); + sinkpad = gst_element_get_static_pad (priv->udpsink[i], "sink"); + + if (priv->protocols & GST_RTSP_LOWER_TRANS_TCP) { + /* make tee for RTP/RTCP */ + priv->tee[i] = gst_element_factory_make ("tee", NULL); + gst_bin_add (bin, priv->tee[i]); + + /* and link to rtpbin send pad */ + pad = gst_element_get_static_pad (priv->tee[i], "sink"); + gst_pad_link (priv->send_src[i], pad); + gst_object_unref (pad); + + /* link tee to udpsink */ + teepad = gst_element_get_request_pad (priv->tee[i], "src_%u"); + gst_pad_link (teepad, sinkpad); + gst_object_unref (teepad); + + /* make queue */ + priv->appqueue[i] = gst_element_factory_make ("queue", NULL); + gst_bin_add (bin, priv->appqueue[i]); + /* and link to tee */ + teepad = gst_element_get_request_pad (priv->tee[i], "src_%u"); + pad = gst_element_get_static_pad (priv->appqueue[i], "sink"); + gst_pad_link (teepad, pad); + gst_object_unref (pad); + gst_object_unref (teepad); + + /* make appsink */ + priv->appsink[i] = gst_element_factory_make ("appsink", NULL); + g_object_set (priv->appsink[i], "async", FALSE, "sync", FALSE, NULL); + g_object_set (priv->appsink[i], "emit-signals", FALSE, NULL); + gst_bin_add (bin, priv->appsink[i]); + gst_app_sink_set_callbacks (GST_APP_SINK_CAST (priv->appsink[i]), + &sink_cb, stream, NULL); + /* and link to queue */ + queuepad = gst_element_get_static_pad (priv->appqueue[i], "src"); + pad = gst_element_get_static_pad (priv->appsink[i], "sink"); + gst_pad_link (queuepad, pad); + gst_object_unref (pad); + gst_object_unref (queuepad); + } else { + /* else only udpsink needed, link it to the session */ + gst_pad_link (priv->send_src[i], sinkpad); + } + gst_object_unref (sinkpad); + + /* For the receiver we create this bit of pipeline for both + * RTP and RTCP. We receive RTP/RTCP on appsrc and udpsrc + * and it is all funneled into the rtpbin receive pad. + * + * .--------. .--------. .--------. + * | udpsrc | | funnel | | rtpbin | + * | src->sink src->sink | + * '--------' | | '--------' + * .--------. | | + * | appsrc | | | + * | src->sink | + * '--------' '--------' + */ + /* make funnel for the RTP/RTCP receivers */ + priv->funnel[i] = gst_element_factory_make ("funnel", NULL); + gst_bin_add (bin, priv->funnel[i]); + + pad = gst_element_get_static_pad (priv->funnel[i], "src"); + gst_pad_link (pad, priv->recv_sink[i]); + gst_object_unref (pad); + + if (priv->udpsrc_v4[i]) { + /* we set and keep these to playing so that they don't cause NO_PREROLL return + * values */ + gst_element_set_state (priv->udpsrc_v4[i], GST_STATE_PLAYING); + gst_element_set_locked_state (priv->udpsrc_v4[i], TRUE); + /* add udpsrc */ + gst_bin_add (bin, priv->udpsrc_v4[i]); + + /* and link to the funnel v4 */ + selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u"); + pad = gst_element_get_static_pad (priv->udpsrc_v4[i], "src"); + gst_pad_link (pad, selpad); + gst_object_unref (pad); + gst_object_unref (selpad); + } + + if (priv->udpsrc_v6[i]) { + gst_element_set_state (priv->udpsrc_v6[i], GST_STATE_PLAYING); + gst_element_set_locked_state (priv->udpsrc_v6[i], TRUE); + gst_bin_add (bin, priv->udpsrc_v6[i]); + + /* and link to the funnel v6 */ + selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u"); + pad = gst_element_get_static_pad (priv->udpsrc_v6[i], "src"); + gst_pad_link (pad, selpad); + gst_object_unref (pad); + gst_object_unref (selpad); + } + + if (priv->protocols & GST_RTSP_LOWER_TRANS_TCP) { + /* make and add appsrc */ + priv->appsrc[i] = gst_element_factory_make ("appsrc", NULL); + gst_bin_add (bin, priv->appsrc[i]); + /* and link to the funnel */ + selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u"); + pad = gst_element_get_static_pad (priv->appsrc[i], "src"); + gst_pad_link (pad, selpad); + gst_object_unref (pad); + gst_object_unref (selpad); + } + + /* check if we need to set to a special state */ + if (state != GST_STATE_NULL) { + if (priv->udpsink[i]) + gst_element_set_state (priv->udpsink[i], state); + if (priv->appsink[i]) + gst_element_set_state (priv->appsink[i], state); + if (priv->appqueue[i]) + gst_element_set_state (priv->appqueue[i], state); + if (priv->tee[i]) + gst_element_set_state (priv->tee[i], state); + if (priv->funnel[i]) + gst_element_set_state (priv->funnel[i], state); + if (priv->appsrc[i]) + gst_element_set_state (priv->appsrc[i], state); + } + } + + /* be notified of caps changes */ + priv->caps_sig = g_signal_connect (priv->send_src[0], "notify::caps", + (GCallback) caps_notify, stream); + + priv->is_joined = TRUE; + g_mutex_unlock (&priv->lock); + + return TRUE; + + /* ERRORS */ +was_joined: + { + g_mutex_unlock (&priv->lock); + return TRUE; + } +no_ports: + { + g_mutex_unlock (&priv->lock); + GST_WARNING ("failed to allocate ports %u", idx); + return FALSE; + } +link_failed: + { + GST_WARNING ("failed to link stream %u", idx); + gst_object_unref (priv->send_rtp_sink); + priv->send_rtp_sink = NULL; + g_mutex_unlock (&priv->lock); + return FALSE; + } +} + +/** + * gst_rtsp_stream_leave_bin: + * @stream: a #GstRTSPStream + * @bin: (transfer none): a #GstBin + * @rtpbin: (transfer none): a rtpbin #GstElement + * + * Remove the elements of @stream from @bin. + * + * Return: %TRUE on success. + */ +gboolean +gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin, + GstElement * rtpbin) +{ + GstRTSPStreamPrivate *priv; + gint i; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + g_return_val_if_fail (GST_IS_BIN (bin), FALSE); + g_return_val_if_fail (GST_IS_ELEMENT (rtpbin), FALSE); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if (!priv->is_joined) + goto was_not_joined; + + /* all transports must be removed by now */ + g_return_val_if_fail (priv->transports == NULL, FALSE); + + clear_tr_cache (priv); + + GST_INFO ("stream %p leaving bin", stream); + + gst_pad_unlink (priv->srcpad, priv->send_rtp_sink); + g_signal_handler_disconnect (priv->send_src[0], priv->caps_sig); + gst_element_release_request_pad (rtpbin, priv->send_rtp_sink); + gst_object_unref (priv->send_rtp_sink); + priv->send_rtp_sink = NULL; + + for (i = 0; i < 2; i++) { + if (priv->udpsink[i]) + gst_element_set_state (priv->udpsink[i], GST_STATE_NULL); + if (priv->appsink[i]) + gst_element_set_state (priv->appsink[i], GST_STATE_NULL); + if (priv->appqueue[i]) + gst_element_set_state (priv->appqueue[i], GST_STATE_NULL); + if (priv->tee[i]) + gst_element_set_state (priv->tee[i], GST_STATE_NULL); + if (priv->funnel[i]) + gst_element_set_state (priv->funnel[i], GST_STATE_NULL); + if (priv->appsrc[i]) + gst_element_set_state (priv->appsrc[i], GST_STATE_NULL); + if (priv->udpsrc_v4[i]) { + /* and set udpsrc to NULL now before removing */ + gst_element_set_locked_state (priv->udpsrc_v4[i], FALSE); + gst_element_set_state (priv->udpsrc_v4[i], GST_STATE_NULL); + /* removing them should also nicely release the request + * pads when they finalize */ + gst_bin_remove (bin, priv->udpsrc_v4[i]); + } + if (priv->udpsrc_v6[i]) { + gst_element_set_locked_state (priv->udpsrc_v6[i], FALSE); + gst_element_set_state (priv->udpsrc_v6[i], GST_STATE_NULL); + gst_bin_remove (bin, priv->udpsrc_v6[i]); + } + if (priv->udpsink[i]) + gst_bin_remove (bin, priv->udpsink[i]); + if (priv->appsrc[i]) + gst_bin_remove (bin, priv->appsrc[i]); + if (priv->appsink[i]) + gst_bin_remove (bin, priv->appsink[i]); + if (priv->appqueue[i]) + gst_bin_remove (bin, priv->appqueue[i]); + if (priv->tee[i]) + gst_bin_remove (bin, priv->tee[i]); + if (priv->funnel[i]) + gst_bin_remove (bin, priv->funnel[i]); + + gst_element_release_request_pad (rtpbin, priv->recv_sink[i]); + gst_object_unref (priv->recv_sink[i]); + priv->recv_sink[i] = NULL; + + priv->udpsrc_v4[i] = NULL; + priv->udpsrc_v6[i] = NULL; + priv->udpsink[i] = NULL; + priv->appsrc[i] = NULL; + priv->appsink[i] = NULL; + priv->appqueue[i] = NULL; + priv->tee[i] = NULL; + priv->funnel[i] = NULL; + } + gst_object_unref (priv->send_src[0]); + priv->send_src[0] = NULL; + + gst_element_release_request_pad (rtpbin, priv->send_src[1]); + gst_object_unref (priv->send_src[1]); + priv->send_src[1] = NULL; + + g_object_unref (priv->session); + priv->session = NULL; + if (priv->caps) + gst_caps_unref (priv->caps); + priv->caps = NULL; + + if (priv->srtpenc) + gst_object_unref (priv->srtpenc); + if (priv->srtpdec) + gst_object_unref (priv->srtpdec); + + priv->is_joined = FALSE; + g_mutex_unlock (&priv->lock); + + return TRUE; + +was_not_joined: + { + g_mutex_unlock (&priv->lock); + return TRUE; + } +} + +/** + * gst_rtsp_stream_get_rtpinfo: + * @stream: a #GstRTSPStream + * @rtptime: (allow-none): result RTP timestamp + * @seq: (allow-none): result RTP seqnum + * @clock_rate: (allow-none): the clock rate + * @running_time: (allow-none): result running-time + * + * Retrieve the current rtptime, seq and running-time. This is used to + * construct a RTPInfo reply header. + * + * Returns: %TRUE when rtptime, seq and running-time could be determined. + */ +gboolean +gst_rtsp_stream_get_rtpinfo (GstRTSPStream * stream, + guint * rtptime, guint * seq, guint * clock_rate, + GstClockTime * running_time) +{ + GstRTSPStreamPrivate *priv; + GstStructure *stats; + GObjectClass *payobjclass; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + + priv = stream->priv; + + payobjclass = G_OBJECT_GET_CLASS (priv->payloader); + + g_mutex_lock (&priv->lock); + + if (g_object_class_find_property (payobjclass, "stats")) { + g_object_get (priv->payloader, "stats", &stats, NULL); + if (stats == NULL) + goto no_stats; + + if (seq) + gst_structure_get_uint (stats, "seqnum", seq); + + if (rtptime) + gst_structure_get_uint (stats, "timestamp", rtptime); + + if (running_time) + gst_structure_get_clock_time (stats, "running-time", running_time); + + if (clock_rate) { + gst_structure_get_uint (stats, "clock-rate", clock_rate); + if (*clock_rate == 0 && running_time) + *running_time = GST_CLOCK_TIME_NONE; + } + gst_structure_free (stats); + } else { + if (!g_object_class_find_property (payobjclass, "seqnum") || + !g_object_class_find_property (payobjclass, "timestamp")) + goto no_stats; + + if (seq) + g_object_get (priv->payloader, "seqnum", seq, NULL); + + if (rtptime) + g_object_get (priv->payloader, "timestamp", rtptime, NULL); + + if (running_time) + *running_time = GST_CLOCK_TIME_NONE; + } + g_mutex_unlock (&priv->lock); + + return TRUE; + + /* ERRORS */ +no_stats: + { + GST_WARNING ("Could not get payloader stats"); + g_mutex_unlock (&priv->lock); + return FALSE; + } +} + +/** + * gst_rtsp_stream_get_caps: + * @stream: a #GstRTSPStream + * + * Retrieve the current caps of @stream. + * + * Returns: (transfer full): the #GstCaps of @stream. use gst_caps_unref() + * after usage. + */ +GstCaps * +gst_rtsp_stream_get_caps (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + GstCaps *result; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if ((result = priv->caps)) + gst_caps_ref (result); + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_stream_recv_rtp: + * @stream: a #GstRTSPStream + * @buffer: (transfer full): a #GstBuffer + * + * Handle an RTP buffer for the stream. This method is usually called when a + * message has been received from a client using the TCP transport. + * + * This function takes ownership of @buffer. + * + * Returns: a GstFlowReturn. + */ +GstFlowReturn +gst_rtsp_stream_recv_rtp (GstRTSPStream * stream, GstBuffer * buffer) +{ + GstRTSPStreamPrivate *priv; + GstFlowReturn ret; + GstElement *element; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), GST_FLOW_ERROR); + priv = stream->priv; + g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); + g_return_val_if_fail (priv->is_joined, FALSE); + + g_mutex_lock (&priv->lock); + if (priv->appsrc[0]) + element = gst_object_ref (priv->appsrc[0]); + else + element = NULL; + g_mutex_unlock (&priv->lock); + + if (element) { + ret = gst_app_src_push_buffer (GST_APP_SRC_CAST (element), buffer); + gst_object_unref (element); + } else { + ret = GST_FLOW_OK; + } + return ret; +} + +/** + * gst_rtsp_stream_recv_rtcp: + * @stream: a #GstRTSPStream + * @buffer: (transfer full): a #GstBuffer + * + * Handle an RTCP buffer for the stream. This method is usually called when a + * message has been received from a client using the TCP transport. + * + * This function takes ownership of @buffer. + * + * Returns: a GstFlowReturn. + */ +GstFlowReturn +gst_rtsp_stream_recv_rtcp (GstRTSPStream * stream, GstBuffer * buffer) +{ + GstRTSPStreamPrivate *priv; + GstFlowReturn ret; + GstElement *element; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), GST_FLOW_ERROR); + priv = stream->priv; + g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); + g_return_val_if_fail (priv->is_joined, FALSE); + + g_mutex_lock (&priv->lock); + if (priv->appsrc[1]) + element = gst_object_ref (priv->appsrc[1]); + else + element = NULL; + g_mutex_unlock (&priv->lock); + + if (element) { + ret = gst_app_src_push_buffer (GST_APP_SRC_CAST (element), buffer); + gst_object_unref (element); + } else { + ret = GST_FLOW_OK; + gst_buffer_unref (buffer); + } + return ret; +} + +/* must be called with lock */ +static gboolean +update_transport (GstRTSPStream * stream, GstRTSPStreamTransport * trans, + gboolean add) +{ + GstRTSPStreamPrivate *priv = stream->priv; + const GstRTSPTransport *tr; + + tr = gst_rtsp_stream_transport_get_transport (trans); + + switch (tr->lower_transport) { + case GST_RTSP_LOWER_TRANS_UDP: + case GST_RTSP_LOWER_TRANS_UDP_MCAST: + { + gchar *dest; + gint min, max; + guint ttl = 0; + + dest = tr->destination; + if (tr->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) { + min = tr->port.min; + max = tr->port.max; + ttl = tr->ttl; + } else { + min = tr->client_port.min; + max = tr->client_port.max; + } + + if (add) { + if (ttl > 0) { + GST_INFO ("setting ttl-mc %d", ttl); + g_object_set (G_OBJECT (priv->udpsink[0]), "ttl-mc", ttl, NULL); + g_object_set (G_OBJECT (priv->udpsink[1]), "ttl-mc", ttl, NULL); + } + GST_INFO ("adding %s:%d-%d", dest, min, max); + g_signal_emit_by_name (priv->udpsink[0], "add", dest, min, NULL); + g_signal_emit_by_name (priv->udpsink[1], "add", dest, max, NULL); + priv->transports = g_list_prepend (priv->transports, trans); + } else { + GST_INFO ("removing %s:%d-%d", dest, min, max); + g_signal_emit_by_name (priv->udpsink[0], "remove", dest, min, NULL); + g_signal_emit_by_name (priv->udpsink[1], "remove", dest, max, NULL); + priv->transports = g_list_remove (priv->transports, trans); + } + priv->transports_cookie++; + break; + } + case GST_RTSP_LOWER_TRANS_TCP: + if (add) { + GST_INFO ("adding TCP %s", tr->destination); + priv->transports = g_list_prepend (priv->transports, trans); + } else { + GST_INFO ("removing TCP %s", tr->destination); + priv->transports = g_list_remove (priv->transports, trans); + } + priv->transports_cookie++; + break; + default: + goto unknown_transport; + } + return TRUE; + + /* ERRORS */ +unknown_transport: + { + GST_INFO ("Unknown transport %d", tr->lower_transport); + return FALSE; + } +} + + +/** + * gst_rtsp_stream_add_transport: + * @stream: a #GstRTSPStream + * @trans: (transfer none): a #GstRTSPStreamTransport + * + * Add the transport in @trans to @stream. The media of @stream will + * then also be send to the values configured in @trans. + * + * @stream must be joined to a bin. + * + * @trans must contain a valid #GstRTSPTransport. + * + * Returns: %TRUE if @trans was added + */ +gboolean +gst_rtsp_stream_add_transport (GstRTSPStream * stream, + GstRTSPStreamTransport * trans) +{ + GstRTSPStreamPrivate *priv; + gboolean res; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + priv = stream->priv; + g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE); + g_return_val_if_fail (priv->is_joined, FALSE); + + g_mutex_lock (&priv->lock); + res = update_transport (stream, trans, TRUE); + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_stream_remove_transport: + * @stream: a #GstRTSPStream + * @trans: (transfer none): a #GstRTSPStreamTransport + * + * Remove the transport in @trans from @stream. The media of @stream will + * not be sent to the values configured in @trans. + * + * @stream must be joined to a bin. + * + * @trans must contain a valid #GstRTSPTransport. + * + * Returns: %TRUE if @trans was removed + */ +gboolean +gst_rtsp_stream_remove_transport (GstRTSPStream * stream, + GstRTSPStreamTransport * trans) +{ + GstRTSPStreamPrivate *priv; + gboolean res; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + priv = stream->priv; + g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE); + g_return_val_if_fail (priv->is_joined, FALSE); + + g_mutex_lock (&priv->lock); + res = update_transport (stream, trans, FALSE); + g_mutex_unlock (&priv->lock); + + return res; +} + +/** + * gst_rtsp_stream_update_crypto: + * @stream: a #GstRTSPStream + * @ssrc: the SSRC + * @crypto: (transfer none) (allow-none): a #GstCaps with crypto info + * + * Update the new crypto information for @ssrc in @stream. If information + * for @ssrc did not exist, it will be added. If information + * for @ssrc existed, it will be replaced. If @crypto is %NULL, it will + * be removed from @stream. + * + * Returns: %TRUE if @crypto could be updated + */ +gboolean +gst_rtsp_stream_update_crypto (GstRTSPStream * stream, + guint ssrc, GstCaps * crypto) +{ + GstRTSPStreamPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + g_return_val_if_fail (crypto == NULL || GST_IS_CAPS (crypto), FALSE); + + priv = stream->priv; + + GST_DEBUG_OBJECT (stream, "update key for %08x", ssrc); + + g_mutex_lock (&priv->lock); + if (crypto) + g_hash_table_insert (priv->keys, GINT_TO_POINTER (ssrc), + gst_caps_ref (crypto)); + else + g_hash_table_remove (priv->keys, GINT_TO_POINTER (ssrc)); + g_mutex_unlock (&priv->lock); + + return TRUE; +} + +/** + * gst_rtsp_stream_get_rtp_socket: + * @stream: a #GstRTSPStream + * @family: the socket family + * + * Get the RTP socket from @stream for a @family. + * + * @stream must be joined to a bin. + * + * Returns: (transfer full) (nullable): the RTP socket or %NULL if no + * socket could be allocated for @family. Unref after usage + */ +GSocket * +gst_rtsp_stream_get_rtp_socket (GstRTSPStream * stream, GSocketFamily family) +{ + GstRTSPStreamPrivate *priv = GST_RTSP_STREAM_GET_PRIVATE (stream); + GSocket *socket; + const gchar *name; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + g_return_val_if_fail (family == G_SOCKET_FAMILY_IPV4 || + family == G_SOCKET_FAMILY_IPV6, NULL); + g_return_val_if_fail (priv->udpsink[0], NULL); + + if (family == G_SOCKET_FAMILY_IPV6) + name = "socket-v6"; + else + name = "socket"; + + g_object_get (priv->udpsink[0], name, &socket, NULL); + + return socket; +} + +/** + * gst_rtsp_stream_get_rtcp_socket: + * @stream: a #GstRTSPStream + * @family: the socket family + * + * Get the RTCP socket from @stream for a @family. + * + * @stream must be joined to a bin. + * + * Returns: (transfer full) (nullable): the RTCP socket or %NULL if no + * socket could be allocated for @family. Unref after usage + */ +GSocket * +gst_rtsp_stream_get_rtcp_socket (GstRTSPStream * stream, GSocketFamily family) +{ + GstRTSPStreamPrivate *priv = GST_RTSP_STREAM_GET_PRIVATE (stream); + GSocket *socket; + const gchar *name; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + g_return_val_if_fail (family == G_SOCKET_FAMILY_IPV4 || + family == G_SOCKET_FAMILY_IPV6, NULL); + g_return_val_if_fail (priv->udpsink[1], NULL); + + if (family == G_SOCKET_FAMILY_IPV6) + name = "socket-v6"; + else + name = "socket"; + + g_object_get (priv->udpsink[1], name, &socket, NULL); + + return socket; +} + +/** + * gst_rtsp_stream_set_seqnum: + * @stream: a #GstRTSPStream + * @seqnum: a new sequence number + * + * Configure the sequence number in the payloader of @stream to @seqnum. + */ +void +gst_rtsp_stream_set_seqnum_offset (GstRTSPStream * stream, guint16 seqnum) +{ + GstRTSPStreamPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + + priv = stream->priv; + + g_object_set (G_OBJECT (priv->payloader), "seqnum-offset", seqnum, NULL); +} + +/** + * gst_rtsp_stream_get_seqnum: + * @stream: a #GstRTSPStream + * + * Get the configured sequence number in the payloader of @stream. + * + * Returns: the sequence number of the payloader. + */ +guint16 +gst_rtsp_stream_get_current_seqnum (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + guint seqnum; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), 0); + + priv = stream->priv; + + g_object_get (G_OBJECT (priv->payloader), "seqnum", &seqnum, NULL); + + return seqnum; +} + +guint64 +gst_rtsp_stream_get_udp_sent_bytes (GstRTSPStream *stream) +{ + GstRTSPStreamPrivate *priv; + guint64 bytes = 0; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), 0); + + priv = stream->priv; + + g_object_get (G_OBJECT (priv->udpsink[0]), "bytes-to-serve", &bytes, NULL); + + return bytes; +} + +/** + * gst_rtsp_stream_transport_filter: + * @stream: a #GstRTSPStream + * @func: (scope call) (allow-none): a callback + * @user_data: (closure): user data passed to @func + * + * Call @func for each transport managed by @stream. The result value of @func + * determines what happens to the transport. @func will be called with @stream + * locked so no further actions on @stream can be performed from @func. + * + * If @func returns #GST_RTSP_FILTER_REMOVE, the transport will be removed from + * @stream. + * + * If @func returns #GST_RTSP_FILTER_KEEP, the transport will remain in @stream. + * + * If @func returns #GST_RTSP_FILTER_REF, the transport will remain in @stream but + * will also be added with an additional ref to the result #GList of this + * function.. + * + * When @func is %NULL, #GST_RTSP_FILTER_REF will be assumed for each transport. + * + * Returns: (element-type GstRTSPStreamTransport) (transfer full): a #GList with all + * transports for which @func returned #GST_RTSP_FILTER_REF. After usage, each + * element in the #GList should be unreffed before the list is freed. + */ +GList * +gst_rtsp_stream_transport_filter (GstRTSPStream * stream, + GstRTSPStreamTransportFilterFunc func, gpointer user_data) +{ + GstRTSPStreamPrivate *priv; + GList *result, *walk, *next; + GHashTable *visited; + guint cookie; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); + + priv = stream->priv; + + result = NULL; + if (func) + visited = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL); + + g_mutex_lock (&priv->lock); +restart: + cookie = priv->transports_cookie; + for (walk = priv->transports; walk; walk = next) { + GstRTSPStreamTransport *trans = walk->data; + GstRTSPFilterResult res; + gboolean changed; + + next = g_list_next (walk); + + if (func) { + /* only visit each transport once */ + if (g_hash_table_contains (visited, trans)) + continue; + + g_hash_table_add (visited, g_object_ref (trans)); + g_mutex_unlock (&priv->lock); + + res = func (stream, trans, user_data); + + g_mutex_lock (&priv->lock); + } else + res = GST_RTSP_FILTER_REF; + + changed = (cookie != priv->transports_cookie); + + switch (res) { + case GST_RTSP_FILTER_REMOVE: + update_transport (stream, trans, FALSE); + break; + case GST_RTSP_FILTER_REF: + result = g_list_prepend (result, g_object_ref (trans)); + break; + case GST_RTSP_FILTER_KEEP: + default: + break; + } + if (changed) + goto restart; + } + g_mutex_unlock (&priv->lock); + + if (func) + g_hash_table_unref (visited); + + return result; +} + +static GstPadProbeReturn +pad_blocking (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + GstRTSPStreamPrivate *priv; + GstRTSPStream *stream; + + stream = user_data; + priv = stream->priv; + + GST_DEBUG_OBJECT (pad, "now blocking"); + + g_mutex_lock (&priv->lock); + priv->blocking = TRUE; + g_mutex_unlock (&priv->lock); + + gst_element_post_message (priv->payloader, + gst_message_new_element (GST_OBJECT_CAST (priv->payloader), + gst_structure_new_empty ("GstRTSPStreamBlocking"))); + + return GST_PAD_PROBE_OK; +} + +/** + * gst_rtsp_stream_set_blocked: + * @stream: a #GstRTSPStream + * @blocked: boolean indicating we should block or unblock + * + * Blocks or unblocks the dataflow on @stream. + * + * Returns: %TRUE on success + */ +gboolean +gst_rtsp_stream_set_blocked (GstRTSPStream * stream, gboolean blocked) +{ + GstRTSPStreamPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if (blocked) { + priv->blocking = FALSE; + if (priv->blocked_id == 0) { + priv->blocked_id = gst_pad_add_probe (priv->srcpad, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER | + GST_PAD_PROBE_TYPE_BUFFER_LIST, pad_blocking, + g_object_ref (stream), g_object_unref); + } + } else { + if (priv->blocked_id != 0) { + gst_pad_remove_probe (priv->srcpad, priv->blocked_id); + priv->blocked_id = 0; + priv->blocking = FALSE; + } + } + g_mutex_unlock (&priv->lock); + + return TRUE; +} + +/** + * gst_rtsp_stream_is_blocking: + * @stream: a #GstRTSPStream + * + * Check if @stream is blocking on a #GstBuffer. + * + * Returns: %TRUE if @stream is blocking + */ +gboolean +gst_rtsp_stream_is_blocking (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + gboolean result; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + result = priv->blocking; + g_mutex_unlock (&priv->lock); + + return result; +} + +/** + * gst_rtsp_stream_query_position: + * @stream: a #GstRTSPStream + * + * Query the position of the stream in %GST_FORMAT_TIME. This only considers + * the RTP parts of the pipeline and not the RTCP parts. + * + * Returns: %TRUE if the position could be queried + */ +gboolean +gst_rtsp_stream_query_position (GstRTSPStream * stream, gint64 * position) +{ + GstRTSPStreamPrivate *priv; + GstElement *sink; + gboolean ret; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if ((sink = priv->udpsink[0])) + gst_object_ref (sink); + g_mutex_unlock (&priv->lock); + + if (!sink) + return FALSE; + + ret = gst_element_query_position (sink, GST_FORMAT_TIME, position); + gst_object_unref (sink); + + return ret; +} + +/** + * gst_rtsp_stream_query_stop: + * @stream: a #GstRTSPStream + * + * Query the stop of the stream in %GST_FORMAT_TIME. This only considers + * the RTP parts of the pipeline and not the RTCP parts. + * + * Returns: %TRUE if the stop could be queried + */ +gboolean +gst_rtsp_stream_query_stop (GstRTSPStream * stream, gint64 * stop) +{ + GstRTSPStreamPrivate *priv; + GstElement *sink; + GstQuery *query; + gboolean ret; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if ((sink = priv->udpsink[0])) + gst_object_ref (sink); + g_mutex_unlock (&priv->lock); + + if (!sink) + return FALSE; + + query = gst_query_new_segment (GST_FORMAT_TIME); + if ((ret = gst_element_query (sink, query))) { + GstFormat format; + + gst_query_parse_segment (query, NULL, &format, NULL, stop); + if (format != GST_FORMAT_TIME) + *stop = -1; + } + gst_query_unref (query); + gst_object_unref (sink); + + return ret; + +} diff --git a/gst/rtsp-server/rtsp-stream.h b/gst/rtsp-server/rtsp-stream.h new file mode 100644 index 0000000..dddbbf4 --- /dev/null +++ b/gst/rtsp-server/rtsp-stream.h @@ -0,0 +1,190 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include +#include +#include +#include + +#ifndef __GST_RTSP_STREAM_H__ +#define __GST_RTSP_STREAM_H__ + +G_BEGIN_DECLS + +/* types for the media stream */ +#define GST_TYPE_RTSP_STREAM (gst_rtsp_stream_get_type ()) +#define GST_IS_RTSP_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_STREAM)) +#define GST_IS_RTSP_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_STREAM)) +#define GST_RTSP_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_STREAM, GstRTSPStreamClass)) +#define GST_RTSP_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_STREAM, GstRTSPStream)) +#define GST_RTSP_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_STREAM, GstRTSPStreamClass)) +#define GST_RTSP_STREAM_CAST(obj) ((GstRTSPStream*)(obj)) +#define GST_RTSP_STREAM_CLASS_CAST(klass) ((GstRTSPStreamClass*)(klass)) + +typedef struct _GstRTSPStream GstRTSPStream; +typedef struct _GstRTSPStreamClass GstRTSPStreamClass; +typedef struct _GstRTSPStreamPrivate GstRTSPStreamPrivate; + +#include "rtsp-stream-transport.h" +#include "rtsp-address-pool.h" +#include "rtsp-session.h" + +/** + * GstRTSPStream: + * + * The definition of a media stream. + */ +struct _GstRTSPStream { + GObject parent; + + /*< private >*/ + GstRTSPStreamPrivate *priv; + gpointer _gst_reserved[GST_PADDING];}; + +struct _GstRTSPStreamClass { + GObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_rtsp_stream_get_type (void); + +GstRTSPStream * gst_rtsp_stream_new (guint idx, GstElement *payloader, + GstPad *srcpad); +guint gst_rtsp_stream_get_index (GstRTSPStream *stream); +guint gst_rtsp_stream_get_pt (GstRTSPStream *stream); +GstPad * gst_rtsp_stream_get_srcpad (GstRTSPStream *stream); + +void gst_rtsp_stream_set_control (GstRTSPStream *stream, const gchar *control); +gchar * gst_rtsp_stream_get_control (GstRTSPStream *stream); +gboolean gst_rtsp_stream_has_control (GstRTSPStream *stream, const gchar *control); + +void gst_rtsp_stream_set_mtu (GstRTSPStream *stream, guint mtu); +guint gst_rtsp_stream_get_mtu (GstRTSPStream *stream); + +void gst_rtsp_stream_set_dscp_qos (GstRTSPStream *stream, gint dscp_qos); +gint gst_rtsp_stream_get_dscp_qos (GstRTSPStream *stream); + +gboolean gst_rtsp_stream_is_transport_supported (GstRTSPStream *stream, + GstRTSPTransport *transport); + +void gst_rtsp_stream_set_profiles (GstRTSPStream *stream, GstRTSPProfile profiles); +GstRTSPProfile gst_rtsp_stream_get_profiles (GstRTSPStream *stream); + +void gst_rtsp_stream_set_protocols (GstRTSPStream *stream, GstRTSPLowerTrans protocols); +GstRTSPLowerTrans gst_rtsp_stream_get_protocols (GstRTSPStream *stream); + +void gst_rtsp_stream_set_address_pool (GstRTSPStream *stream, GstRTSPAddressPool *pool); +GstRTSPAddressPool * + gst_rtsp_stream_get_address_pool (GstRTSPStream *stream); + +GstRTSPAddress * gst_rtsp_stream_reserve_address (GstRTSPStream *stream, + const gchar * address, + guint port, + guint n_ports, + guint ttl); + +gboolean gst_rtsp_stream_join_bin (GstRTSPStream *stream, + GstBin *bin, GstElement *rtpbin, + GstState state); +gboolean gst_rtsp_stream_leave_bin (GstRTSPStream *stream, + GstBin *bin, GstElement *rtpbin); + +gboolean gst_rtsp_stream_set_blocked (GstRTSPStream * stream, + gboolean blocked); +gboolean gst_rtsp_stream_is_blocking (GstRTSPStream * stream); + +void gst_rtsp_stream_get_server_port (GstRTSPStream *stream, + GstRTSPRange *server_port, + GSocketFamily family); +GstRTSPAddress * gst_rtsp_stream_get_multicast_address (GstRTSPStream *stream, + GSocketFamily family); + + +GObject * gst_rtsp_stream_get_rtpsession (GstRTSPStream *stream); + +void gst_rtsp_stream_get_ssrc (GstRTSPStream *stream, + guint *ssrc); + +gboolean gst_rtsp_stream_get_rtpinfo (GstRTSPStream *stream, + guint *rtptime, guint *seq, + guint *clock_rate, + GstClockTime *running_time); +GstCaps * gst_rtsp_stream_get_caps (GstRTSPStream *stream); + +GstFlowReturn gst_rtsp_stream_recv_rtp (GstRTSPStream *stream, + GstBuffer *buffer); +GstFlowReturn gst_rtsp_stream_recv_rtcp (GstRTSPStream *stream, + GstBuffer *buffer); + +gboolean gst_rtsp_stream_add_transport (GstRTSPStream *stream, + GstRTSPStreamTransport *trans); +gboolean gst_rtsp_stream_remove_transport (GstRTSPStream *stream, + GstRTSPStreamTransport *trans); + +GSocket * gst_rtsp_stream_get_rtp_socket (GstRTSPStream *stream, + GSocketFamily family); +GSocket * gst_rtsp_stream_get_rtcp_socket (GstRTSPStream *stream, + GSocketFamily family); + +gboolean gst_rtsp_stream_update_crypto (GstRTSPStream * stream, + guint ssrc, GstCaps * crypto); + + +gboolean gst_rtsp_stream_query_position (GstRTSPStream * stream, + gint64 * position); +gboolean gst_rtsp_stream_query_stop (GstRTSPStream * stream, + gint64 * stop); + +void gst_rtsp_stream_set_seqnum_offset (GstRTSPStream *stream, guint16 seqnum); +guint16 gst_rtsp_stream_get_current_seqnum (GstRTSPStream *stream); +guint64 gst_rtsp_stream_get_udp_sent_bytes (GstRTSPStream *stream); + +/** + * GstRTSPStreamTransportFilterFunc: + * @stream: a #GstRTSPStream object + * @trans: a #GstRTSPStreamTransport in @stream + * @user_data: user data that has been given to gst_rtsp_stream_transport_filter() + * + * This function will be called by the gst_rtsp_stream_transport_filter(). An + * implementation should return a value of #GstRTSPFilterResult. + * + * When this function returns #GST_RTSP_FILTER_REMOVE, @trans will be removed + * from @stream. + * + * A return value of #GST_RTSP_FILTER_KEEP will leave @trans untouched in + * @stream. + * + * A value of #GST_RTSP_FILTER_REF will add @trans to the result #GList of + * gst_rtsp_stream_transport_filter(). + * + * Returns: a #GstRTSPFilterResult. + */ +typedef GstRTSPFilterResult (*GstRTSPStreamTransportFilterFunc) (GstRTSPStream *stream, + GstRTSPStreamTransport *trans, + gpointer user_data); + +GList * gst_rtsp_stream_transport_filter (GstRTSPStream *stream, + GstRTSPStreamTransportFilterFunc func, + gpointer user_data); + +G_END_DECLS + +#endif /* __GST_RTSP_STREAM_H__ */ diff --git a/gst/rtsp-server/rtsp-thread-pool.c b/gst/rtsp-server/rtsp-thread-pool.c new file mode 100644 index 0000000..a8cce78 --- /dev/null +++ b/gst/rtsp-server/rtsp-thread-pool.c @@ -0,0 +1,561 @@ +/* GStreamer + * Copyright (C) 2013 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-thread-pool + * @short_description: A pool of threads + * @see_also: #GstRTSPMedia, #GstRTSPClient + * + * A #GstRTSPThreadPool manages reusable threads for various server tasks. + * Currently the defined thread types can be found in #GstRTSPThreadType. + * + * Threads of type #GST_RTSP_THREAD_TYPE_CLIENT are used to handle requests from + * a connected client. With gst_rtsp_thread_pool_get_max_threads() a maximum + * number of threads can be set after which the pool will start to reuse the + * same thread for multiple clients. + * + * Threads of type #GST_RTSP_THREAD_TYPE_MEDIA will be used to perform the state + * changes of the media pipelines and handle its bus messages. + * + * gst_rtsp_thread_pool_get_thread() can be used to create a #GstRTSPThread + * object of the right type. The thread object contains a mainloop and context + * that run in a seperate thread and can be used to attached sources to. + * + * gst_rtsp_thread_reuse() can be used to reuse a thread for multiple purposes. + * If all gst_rtsp_thread_reuse() calls are matched with a + * gst_rtsp_thread_stop() call, the mainloop will be quit and the thread will + * stop. + * + * To configure the threads, a subclass of this object should be made and the + * virtual methods should be overriden to implement the desired functionality. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include + +#include "rtsp-thread-pool.h" + +typedef struct _GstRTSPThreadImpl +{ + GstRTSPThread thread; + + gint reused; + GSource *source; +} GstRTSPThreadImpl; + +GST_DEFINE_MINI_OBJECT_TYPE (GstRTSPThread, gst_rtsp_thread); + +static void gst_rtsp_thread_init (GstRTSPThreadImpl * impl); + +static void +_gst_rtsp_thread_free (GstRTSPThreadImpl * impl) +{ + GST_DEBUG ("free thread %p", impl); + + g_source_unref (impl->source); + g_main_loop_unref (impl->thread.loop); + g_main_context_unref (impl->thread.context); + g_slice_free1 (sizeof (GstRTSPThreadImpl), impl); +} + +static GstRTSPThread * +_gst_rtsp_thread_copy (GstRTSPThreadImpl * impl) +{ + GstRTSPThreadImpl *copy; + + GST_DEBUG ("copy thread %p", impl); + + copy = g_slice_new0 (GstRTSPThreadImpl); + gst_rtsp_thread_init (copy); + copy->thread.context = g_main_context_ref (impl->thread.context); + copy->thread.loop = g_main_loop_ref (impl->thread.loop); + + return GST_RTSP_THREAD (copy); +} + +static void +gst_rtsp_thread_init (GstRTSPThreadImpl * impl) +{ + gst_mini_object_init (GST_MINI_OBJECT_CAST (impl), 0, + GST_TYPE_RTSP_THREAD, + (GstMiniObjectCopyFunction) _gst_rtsp_thread_copy, NULL, + (GstMiniObjectFreeFunction) _gst_rtsp_thread_free); + + g_atomic_int_set (&impl->reused, 1); +} + +/** + * gst_rtsp_thread_new: + * @type: the thread type + * + * Create a new thread object that can run a mainloop. + * + * Returns: (transfer full): a #GstRTSPThread. + */ +GstRTSPThread * +gst_rtsp_thread_new (GstRTSPThreadType type) +{ + GstRTSPThreadImpl *impl; + + impl = g_slice_new0 (GstRTSPThreadImpl); + + gst_rtsp_thread_init (impl); + impl->thread.type = type; + impl->thread.context = g_main_context_new (); + impl->thread.loop = g_main_loop_new (impl->thread.context, TRUE); + + return GST_RTSP_THREAD (impl); +} + +/** + * gst_rtsp_thread_reuse: + * @thread: (transfer none): a #GstRTSPThread + * + * Reuse the mainloop of @thread + * + * Returns: %TRUE if the mainloop could be reused + */ +gboolean +gst_rtsp_thread_reuse (GstRTSPThread * thread) +{ + GstRTSPThreadImpl *impl = (GstRTSPThreadImpl *) thread; + gboolean res; + + g_return_val_if_fail (GST_IS_RTSP_THREAD (thread), FALSE); + + GST_DEBUG ("reuse thread %p", thread); + + res = g_atomic_int_add (&impl->reused, 1) > 0; + if (res) + gst_rtsp_thread_ref (thread); + + return res; +} + +static gboolean +do_quit (GstRTSPThread * thread) +{ + GST_DEBUG ("stop mainloop of thread %p", thread); + g_main_loop_quit (thread->loop); + return FALSE; +} + +/** + * gst_rtsp_thread_stop: + * @thread: (transfer full): a #GstRTSPThread + * + * Stop and unref @thread. When no threads are using the mainloop, the thread + * will be stopped and the final ref to @thread will be released. + */ +void +gst_rtsp_thread_stop (GstRTSPThread * thread) +{ + GstRTSPThreadImpl *impl = (GstRTSPThreadImpl *) thread; + + g_return_if_fail (GST_IS_RTSP_THREAD (thread)); + + GST_DEBUG ("stop thread %p", thread); + + if (g_atomic_int_dec_and_test (&impl->reused)) { + GST_DEBUG ("add idle source to quit mainloop of thread %p", thread); + impl->source = g_idle_source_new (); + g_source_set_callback (impl->source, (GSourceFunc) do_quit, + thread, (GDestroyNotify) gst_rtsp_thread_unref); + g_source_attach (impl->source, thread->context); + } else + gst_rtsp_thread_unref (thread); +} + +#define GST_RTSP_THREAD_POOL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_THREAD_POOL, GstRTSPThreadPoolPrivate)) + +struct _GstRTSPThreadPoolPrivate +{ + GMutex lock; + + gint max_threads; + /* currently used mainloops */ + GQueue threads; +}; + +#define DEFAULT_MAX_THREADS 1 + +enum +{ + PROP_0, + PROP_MAX_THREADS, + PROP_LAST +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_thread_pool_debug); +#define GST_CAT_DEFAULT rtsp_thread_pool_debug + +static GQuark thread_pool; + +static void gst_rtsp_thread_pool_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_thread_pool_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); +static void gst_rtsp_thread_pool_finalize (GObject * obj); + +static gpointer do_loop (GstRTSPThread * thread); +static GstRTSPThread *default_get_thread (GstRTSPThreadPool * pool, + GstRTSPThreadType type, GstRTSPContext * ctx); + +G_DEFINE_TYPE (GstRTSPThreadPool, gst_rtsp_thread_pool, G_TYPE_OBJECT); + +static void +gst_rtsp_thread_pool_class_init (GstRTSPThreadPoolClass * klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (GstRTSPThreadPoolPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gst_rtsp_thread_pool_get_property; + gobject_class->set_property = gst_rtsp_thread_pool_set_property; + gobject_class->finalize = gst_rtsp_thread_pool_finalize; + + /** + * GstRTSPThreadPool::max-threads: + * + * The maximum amount of threads to use for client connections. A value of + * 0 means to use only the mainloop, -1 means an unlimited amount of + * threads. + */ + g_object_class_install_property (gobject_class, PROP_MAX_THREADS, + g_param_spec_int ("max-threads", "Max Threads", + "The maximum amount of threads to use for client connections " + "(0 = only mainloop, -1 = unlimited)", -1, G_MAXINT, + DEFAULT_MAX_THREADS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + klass->get_thread = default_get_thread; + + GST_DEBUG_CATEGORY_INIT (rtsp_thread_pool_debug, "rtspthreadpool", 0, + "GstRTSPThreadPool"); + + thread_pool = g_quark_from_string ("gst.rtsp.thread.pool"); +} + +static void +gst_rtsp_thread_pool_init (GstRTSPThreadPool * pool) +{ + GstRTSPThreadPoolPrivate *priv; + + pool->priv = priv = GST_RTSP_THREAD_POOL_GET_PRIVATE (pool); + + g_mutex_init (&priv->lock); + priv->max_threads = DEFAULT_MAX_THREADS; + g_queue_init (&priv->threads); +} + +static void +gst_rtsp_thread_pool_finalize (GObject * obj) +{ + GstRTSPThreadPool *pool = GST_RTSP_THREAD_POOL (obj); + GstRTSPThreadPoolPrivate *priv = pool->priv; + + GST_INFO ("finalize pool %p", pool); + + g_queue_clear (&priv->threads); + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (gst_rtsp_thread_pool_parent_class)->finalize (obj); +} + +static void +gst_rtsp_thread_pool_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec) +{ + GstRTSPThreadPool *pool = GST_RTSP_THREAD_POOL (object); + + switch (propid) { + case PROP_MAX_THREADS: + g_value_set_int (value, gst_rtsp_thread_pool_get_max_threads (pool)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static void +gst_rtsp_thread_pool_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ + GstRTSPThreadPool *pool = GST_RTSP_THREAD_POOL (object); + + switch (propid) { + case PROP_MAX_THREADS: + gst_rtsp_thread_pool_set_max_threads (pool, g_value_get_int (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); + } +} + +static gpointer +do_loop (GstRTSPThread * thread) +{ + GstRTSPThreadPoolPrivate *priv; + GstRTSPThreadPoolClass *klass; + GstRTSPThreadPool *pool; + + pool = gst_mini_object_get_qdata (GST_MINI_OBJECT (thread), thread_pool); + priv = pool->priv; + + klass = GST_RTSP_THREAD_POOL_GET_CLASS (pool); + + if (klass->thread_enter) + klass->thread_enter (pool, thread); + + GST_INFO ("enter mainloop of thread %p", thread); + g_main_loop_run (thread->loop); + GST_INFO ("exit mainloop of thread %p", thread); + + if (klass->thread_leave) + klass->thread_leave (pool, thread); + + g_mutex_lock (&priv->lock); + g_queue_remove (&priv->threads, thread); + g_mutex_unlock (&priv->lock); + + gst_rtsp_thread_unref (thread); + + return NULL; +} + +/** + * gst_rtsp_thread_pool_new: + * + * Create a new #GstRTSPThreadPool instance. + * + * Returns: (transfer full): a new #GstRTSPThreadPool + */ +GstRTSPThreadPool * +gst_rtsp_thread_pool_new (void) +{ + GstRTSPThreadPool *result; + + result = g_object_new (GST_TYPE_RTSP_THREAD_POOL, NULL); + + return result; +} + +/** + * gst_rtsp_thread_pool_set_max_threads: + * @pool: a #GstRTSPThreadPool + * @max_threads: maximum threads + * + * Set the maximum threads used by the pool to handle client requests. + * A value of 0 will use the pool mainloop, a value of -1 will use an + * unlimited number of threads. + */ +void +gst_rtsp_thread_pool_set_max_threads (GstRTSPThreadPool * pool, + gint max_threads) +{ + GstRTSPThreadPoolPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_THREAD_POOL (pool)); + + priv = pool->priv; + + g_mutex_lock (&priv->lock); + priv->max_threads = max_threads; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_thread_pool_get_max_threads: + * @pool: a #GstRTSPThreadPool + * + * Get the maximum number of threads used for client connections. + * See gst_rtsp_thread_pool_set_max_threads(). + * + * Returns: the maximum number of threads. + */ +gint +gst_rtsp_thread_pool_get_max_threads (GstRTSPThreadPool * pool) +{ + GstRTSPThreadPoolPrivate *priv; + gint res; + + g_return_val_if_fail (GST_IS_RTSP_THREAD_POOL (pool), -1); + + priv = pool->priv; + + g_mutex_lock (&priv->lock); + res = priv->max_threads; + g_mutex_unlock (&priv->lock); + + return res; +} + +static GstRTSPThread * +make_thread (GstRTSPThreadPool * pool, GstRTSPThreadType type, + GstRTSPContext * ctx) +{ + GstRTSPThreadPoolClass *klass; + GstRTSPThread *thread; + + klass = GST_RTSP_THREAD_POOL_GET_CLASS (pool); + + thread = gst_rtsp_thread_new (type); + gst_mini_object_set_qdata (GST_MINI_OBJECT (thread), thread_pool, + g_object_ref (pool), g_object_unref); + + GST_DEBUG_OBJECT (pool, "new thread %p", thread); + + if (klass->configure_thread) + klass->configure_thread (pool, thread, ctx); + + return thread; +} + +static GstRTSPThread * +default_get_thread (GstRTSPThreadPool * pool, + GstRTSPThreadType type, GstRTSPContext * ctx) +{ + GstRTSPThreadPoolPrivate *priv = pool->priv; + GstRTSPThreadPoolClass *klass; + GstRTSPThread *thread; + GError *error = NULL; + + klass = GST_RTSP_THREAD_POOL_GET_CLASS (pool); + + switch (type) { + case GST_RTSP_THREAD_TYPE_CLIENT: + if (priv->max_threads == 0) { + /* no threads allowed */ + GST_DEBUG_OBJECT (pool, "no client threads allowed"); + thread = NULL; + } else { + g_mutex_lock (&priv->lock); + retry: + if (priv->max_threads > 0 && + g_queue_get_length (&priv->threads) >= priv->max_threads) { + /* max threads reached, recycle from queue */ + thread = g_queue_pop_head (&priv->threads); + GST_DEBUG_OBJECT (pool, "recycle client thread %p", thread); + if (!gst_rtsp_thread_reuse (thread)) { + GST_DEBUG_OBJECT (pool, "thread %p stopping, retry", thread); + /* this can happen if we just decremented the reuse counter of the + * thread and signaled the mainloop that it should stop. We leave + * the thread out of the queue now, there is no point to add it + * again, it will be removed from the mainloop otherwise after it + * stops. */ + goto retry; + } + } else { + /* make more threads */ + GST_DEBUG_OBJECT (pool, "make new client thread"); + thread = make_thread (pool, type, ctx); + + if (!g_thread_pool_push (klass->pool, gst_rtsp_thread_ref (thread), + &error)) + goto thread_error; + } + g_queue_push_tail (&priv->threads, thread); + g_mutex_unlock (&priv->lock); + } + break; + case GST_RTSP_THREAD_TYPE_MEDIA: + GST_DEBUG_OBJECT (pool, "make new media thread"); + thread = make_thread (pool, type, ctx); + + if (!g_thread_pool_push (klass->pool, gst_rtsp_thread_ref (thread), + &error)) + goto thread_error; + break; + default: + thread = NULL; + break; + } + return thread; + + /* ERRORS */ +thread_error: + { + GST_ERROR_OBJECT (pool, "failed to push thread %s", error->message); + gst_rtsp_thread_unref (thread); + /* drop also the ref dedicated for the pool */ + gst_rtsp_thread_unref (thread); + g_clear_error (&error); + return NULL; + } +} + +/** + * gst_rtsp_thread_pool_get_thread: + * @pool: a #GstRTSPThreadPool + * @type: the #GstRTSPThreadType + * @ctx: (transfer none): a #GstRTSPContext + * + * Get a new #GstRTSPThread for @type and @ctx. + * + * Returns: (transfer full): a new #GstRTSPThread, gst_rtsp_thread_stop() after usage + */ +GstRTSPThread * +gst_rtsp_thread_pool_get_thread (GstRTSPThreadPool * pool, + GstRTSPThreadType type, GstRTSPContext * ctx) +{ + GstRTSPThreadPoolClass *klass; + GstRTSPThread *result = NULL; + + g_return_val_if_fail (GST_IS_RTSP_THREAD_POOL (pool), NULL); + + klass = GST_RTSP_THREAD_POOL_GET_CLASS (pool); + + /* We want to be thread safe as there might be 2 threads wanting to get new + * #GstRTSPThread at the same time + */ + if (G_UNLIKELY (!g_atomic_pointer_get (&klass->pool))) { + GThreadPool *t_pool; + t_pool = g_thread_pool_new ((GFunc) do_loop, klass, -1, FALSE, NULL); + if (!g_atomic_pointer_compare_and_exchange (&klass->pool, NULL, t_pool)) + g_thread_pool_free (t_pool, FALSE, TRUE); + } + + if (klass->get_thread) + result = klass->get_thread (pool, type, ctx); + + return result; +} + +/** + * gst_rtsp_thread_pool_cleanup: + * + * Wait for all tasks to be stopped and free all allocated resources. This is + * mainly used in test suites to ensure proper cleanup of internal data + * structures. + */ +void +gst_rtsp_thread_pool_cleanup (void) +{ + GstRTSPThreadPoolClass *klass; + + klass = + GST_RTSP_THREAD_POOL_CLASS (g_type_class_peek + (gst_rtsp_thread_pool_get_type ())); + if (klass->pool != NULL) { + g_thread_pool_free (klass->pool, FALSE, TRUE); + klass->pool = NULL; + } +} diff --git a/gst/rtsp-server/rtsp-thread-pool.h b/gst/rtsp-server/rtsp-thread-pool.h new file mode 100644 index 0000000..e360034 --- /dev/null +++ b/gst/rtsp-server/rtsp-thread-pool.h @@ -0,0 +1,179 @@ +/* GStreamer + * Copyright (C) 2010 Wim Taymans + * + * 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. + */ + +#include + +#ifndef __GST_RTSP_THREAD_POOL_H__ +#define __GST_RTSP_THREAD_POOL_H__ + +typedef struct _GstRTSPThread GstRTSPThread; +typedef struct _GstRTSPThreadPool GstRTSPThreadPool; +typedef struct _GstRTSPThreadPoolClass GstRTSPThreadPoolClass; +typedef struct _GstRTSPThreadPoolPrivate GstRTSPThreadPoolPrivate; + +#include "rtsp-client.h" + +G_BEGIN_DECLS + +#define GST_TYPE_RTSP_THREAD_POOL (gst_rtsp_thread_pool_get_type ()) +#define GST_IS_RTSP_THREAD_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_THREAD_POOL)) +#define GST_IS_RTSP_THREAD_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_THREAD_POOL)) +#define GST_RTSP_THREAD_POOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_THREAD_POOL, GstRTSPThreadPoolClass)) +#define GST_RTSP_THREAD_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_THREAD_POOL, GstRTSPThreadPool)) +#define GST_RTSP_THREAD_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_THREAD_POOL, GstRTSPThreadPoolClass)) +#define GST_RTSP_THREAD_POOL_CAST(obj) ((GstRTSPThreadPool*)(obj)) +#define GST_RTSP_THREAD_POOL_CLASS_CAST(klass) ((GstRTSPThreadPoolClass*)(klass)) + +GType gst_rtsp_thread_get_type (void); + +#define GST_TYPE_RTSP_THREAD (gst_rtsp_thread_get_type ()) +#define GST_IS_RTSP_THREAD(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_RTSP_THREAD)) +#define GST_RTSP_THREAD_CAST(obj) ((GstRTSPThread*)(obj)) +#define GST_RTSP_THREAD(obj) (GST_RTSP_THREAD_CAST(obj)) + +/** + * GstRTSPThreadType: + * @GST_RTSP_THREAD_TYPE_CLIENT: a thread to handle the client communication + * @GST_RTSP_THREAD_TYPE_MEDIA: a thread to handle media + * + * Different thread types + */ +typedef enum +{ + GST_RTSP_THREAD_TYPE_CLIENT, + GST_RTSP_THREAD_TYPE_MEDIA +} GstRTSPThreadType; + +/** + * GstRTSPThread: + * @mini_object: parent #GstMiniObject + * @type: the thread type + * @context: a #GMainContext + * @loop: a #GMainLoop + * + * Structure holding info about a mainloop running in a thread + */ +struct _GstRTSPThread { + GstMiniObject mini_object; + + GstRTSPThreadType type; + GMainContext *context; + GMainLoop *loop; +}; + +GstRTSPThread * gst_rtsp_thread_new (GstRTSPThreadType type); + +gboolean gst_rtsp_thread_reuse (GstRTSPThread * thread); +void gst_rtsp_thread_stop (GstRTSPThread * thread); + +/** + * gst_rtsp_thread_ref: + * @thread: The thread to refcount + * + * Increase the refcount of this thread. + * + * Returns: (transfer full): @thread (for convenience when doing assignments) + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC GstRTSPThread * gst_rtsp_thread_ref (GstRTSPThread * thread); +#endif + +static inline GstRTSPThread * +gst_rtsp_thread_ref (GstRTSPThread * thread) +{ + return (GstRTSPThread *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (thread)); +} + +/** + * gst_rtsp_thread_unref: + * @thread: (transfer full): the thread to refcount + * + * Decrease the refcount of an thread, freeing it if the refcount reaches 0. + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC void gst_rtsp_thread_unref (GstRTSPPermissions * thread); +#endif + + +static inline void +gst_rtsp_thread_unref (GstRTSPThread * thread) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (thread)); +} + +/** + * GstRTSPThreadPool: + * + * The thread pool structure. + */ +struct _GstRTSPThreadPool { + GObject parent; + + /*< private >*/ + GstRTSPThreadPoolPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPThreadPoolClass: + * @pool: a #GThreadPool used internally + * @get_thread: this function should make or reuse an existing thread that runs + * a mainloop. + * @configure_thread: configure a thread object. this vmethod is called when + * a new thread has been created and should be configured. + * @thread_enter: called from the thread when it is entered + * @thread_leave: called from the thread when it is left + * + * Class for managing threads. + */ +struct _GstRTSPThreadPoolClass { + GObjectClass parent_class; + + GThreadPool *pool; + + GstRTSPThread * (*get_thread) (GstRTSPThreadPool *pool, + GstRTSPThreadType type, + GstRTSPContext *ctx); + void (*configure_thread) (GstRTSPThreadPool *pool, + GstRTSPThread * thread, + GstRTSPContext *ctx); + + void (*thread_enter) (GstRTSPThreadPool *pool, + GstRTSPThread *thread); + void (*thread_leave) (GstRTSPThreadPool *pool, + GstRTSPThread *thread); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_rtsp_thread_pool_get_type (void); + +GstRTSPThreadPool * gst_rtsp_thread_pool_new (void); + +void gst_rtsp_thread_pool_set_max_threads (GstRTSPThreadPool * pool, gint max_threads); +gint gst_rtsp_thread_pool_get_max_threads (GstRTSPThreadPool * pool); + +GstRTSPThread * gst_rtsp_thread_pool_get_thread (GstRTSPThreadPool *pool, + GstRTSPThreadType type, + GstRTSPContext *ctx); +void gst_rtsp_thread_pool_cleanup (void); +G_END_DECLS + +#endif /* __GST_RTSP_THREAD_POOL_H__ */ diff --git a/gst/rtsp-server/rtsp-token.c b/gst/rtsp-server/rtsp-token.c new file mode 100644 index 0000000..69250f9 --- /dev/null +++ b/gst/rtsp-server/rtsp-token.c @@ -0,0 +1,251 @@ +/* GStreamer + * Copyright (C) 2010 Wim Taymans + * + * 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. + */ +/** + * SECTION:rtsp-token + * @short_description: Roles and permissions for a client + * @see_also: #GstRTSPClient, #GstRTSPPermissions, #GstRTSPAuth + * + * A #GstRTSPToken contains the permissions and roles of the user + * performing the current request. A token is usually created when a user is + * authenticated by the #GstRTSPAuth object and is then placed as the current + * token for the current request. + * + * #GstRTSPAuth can use the token and its contents to check authorization for + * various operations by comparing the token to the #GstRTSPPermissions of the + * object. + * + * The accepted values of the token are entirely defined by the #GstRTSPAuth + * object that implements the security policy. + * + * Last reviewed on 2013-07-15 (1.0.0) + */ + +#include + +#include "rtsp-token.h" + +typedef struct _GstRTSPTokenImpl +{ + GstRTSPToken token; + + GstStructure *structure; +} GstRTSPTokenImpl; + +#define GST_RTSP_TOKEN_STRUCTURE(t) (((GstRTSPTokenImpl *)(t))->structure) + +//GST_DEBUG_CATEGORY_STATIC (rtsp_token_debug); +//#define GST_CAT_DEFAULT rtsp_token_debug + +GST_DEFINE_MINI_OBJECT_TYPE (GstRTSPToken, gst_rtsp_token); + +static void gst_rtsp_token_init (GstRTSPTokenImpl * token, + GstStructure * structure); + +static void +_gst_rtsp_token_free (GstRTSPToken * token) +{ + GstRTSPTokenImpl *impl = (GstRTSPTokenImpl *) token; + + gst_structure_set_parent_refcount (impl->structure, NULL); + gst_structure_free (impl->structure); + + g_slice_free1 (sizeof (GstRTSPTokenImpl), token); +} + +static GstRTSPToken * +_gst_rtsp_token_copy (GstRTSPTokenImpl * token) +{ + GstRTSPTokenImpl *copy; + GstStructure *structure; + + structure = gst_structure_copy (token->structure); + + copy = g_slice_new0 (GstRTSPTokenImpl); + gst_rtsp_token_init (copy, structure); + + return (GstRTSPToken *) copy; +} + +static void +gst_rtsp_token_init (GstRTSPTokenImpl * token, GstStructure * structure) +{ + gst_mini_object_init (GST_MINI_OBJECT_CAST (token), 0, + GST_TYPE_RTSP_TOKEN, + (GstMiniObjectCopyFunction) _gst_rtsp_token_copy, NULL, + (GstMiniObjectFreeFunction) _gst_rtsp_token_free); + + token->structure = structure; + gst_structure_set_parent_refcount (token->structure, + &token->token.mini_object.refcount); +} + +/** + * gst_rtsp_token_new_empty: + * + * Create a new empty Authorization token. + * + * Returns: (transfer full): a new empty authorization token. + */ +GstRTSPToken * +gst_rtsp_token_new_empty (void) +{ + GstRTSPTokenImpl *token; + GstStructure *s; + + s = gst_structure_new_empty ("GstRTSPToken"); + g_return_val_if_fail (s != NULL, NULL); + + token = g_slice_new0 (GstRTSPTokenImpl); + gst_rtsp_token_init (token, s); + + return (GstRTSPToken *) token; +} + +/** + * gst_rtsp_token_new: + * @firstfield: the first fieldname + * @...: additional arguments + * + * Create a new Authorization token with the given fieldnames and values. + * Arguments are given similar to gst_structure_new(). + * + * Returns: (transfer full): a new authorization token. + */ +GstRTSPToken * +gst_rtsp_token_new (const gchar * firstfield, ...) +{ + GstRTSPToken *result; + va_list var_args; + + va_start (var_args, firstfield); + result = gst_rtsp_token_new_valist (firstfield, var_args); + va_end (var_args); + + return result; +} + +/** + * gst_rtsp_token_new_valist: + * @firstfield: the first fieldname + * @var_args: additional arguments + * + * Create a new Authorization token with the given fieldnames and values. + * Arguments are given similar to gst_structure_new_valist(). + * + * Returns: (transfer full): a new authorization token. + */ +GstRTSPToken * +gst_rtsp_token_new_valist (const gchar * firstfield, va_list var_args) +{ + GstRTSPToken *token; + GstStructure *s; + + g_return_val_if_fail (firstfield != NULL, NULL); + + token = gst_rtsp_token_new_empty (); + s = GST_RTSP_TOKEN_STRUCTURE (token); + gst_structure_set_valist (s, firstfield, var_args); + + return token; +} + + +/** + * gst_rtsp_token_get_structure: + * @token: The #GstRTSPToken. + * + * Access the structure of the token. + * + * Returns: (transfer none): The structure of the token. The structure is still + * owned by the token, which means that you should not free it and that the + * pointer becomes invalid when you free the token. + * + * MT safe. + */ +const GstStructure * +gst_rtsp_token_get_structure (GstRTSPToken * token) +{ + g_return_val_if_fail (GST_IS_RTSP_TOKEN (token), NULL); + + return GST_RTSP_TOKEN_STRUCTURE (token); +} + +/** + * gst_rtsp_token_writable_structure: + * @token: The #GstRTSPToken. + * + * Get a writable version of the structure. + * + * Returns: (transfer none): The structure of the token. The structure is still + * owned by the token, which means that you should not free it and that the + * pointer becomes invalid when you free the token. This function checks if + * @token is writable and will never return %NULL. + * + * MT safe. + */ +GstStructure * +gst_rtsp_token_writable_structure (GstRTSPToken * token) +{ + g_return_val_if_fail (GST_IS_RTSP_TOKEN (token), NULL); + g_return_val_if_fail (gst_mini_object_is_writable (GST_MINI_OBJECT_CAST + (token)), NULL); + + return GST_RTSP_TOKEN_STRUCTURE (token); +} + +/** + * gst_rtsp_token_get_string: + * @token: a #GstRTSPToken + * @field: a field name + * + * Get the string value of @field in @token. + * + * Returns: (transfer none) (nullable): the string value of @field in + * @token or %NULL when @field is not defined in @token. The string + * becomes invalid when you free @token. + */ +const gchar * +gst_rtsp_token_get_string (GstRTSPToken * token, const gchar * field) +{ + return gst_structure_get_string (GST_RTSP_TOKEN_STRUCTURE (token), field); +} + +/** + * gst_rtsp_token_is_allowed: + * @token: a #GstRTSPToken + * @field: a field name + * + * Check if @token has a boolean @field and if it is set to %TRUE. + * + * Returns: %TRUE if @token has a boolean field named @field set to %TRUE. + */ +gboolean +gst_rtsp_token_is_allowed (GstRTSPToken * token, const gchar * field) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_RTSP_TOKEN (token), FALSE); + g_return_val_if_fail (field != NULL, FALSE); + + if (!gst_structure_get_boolean (GST_RTSP_TOKEN_STRUCTURE (token), field, + &result)) + result = FALSE; + + return result; +} diff --git a/gst/rtsp-server/rtsp-token.h b/gst/rtsp-server/rtsp-token.h new file mode 100644 index 0000000..265d8d3 --- /dev/null +++ b/gst/rtsp-server/rtsp-token.h @@ -0,0 +1,97 @@ +/* GStreamer + * Copyright (C) 2010 Wim Taymans + * + * 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. + */ + +#include + +#ifndef __GST_RTSP_TOKEN_H__ +#define __GST_RTSP_TOKEN_H__ + +typedef struct _GstRTSPToken GstRTSPToken; + +#include "rtsp-auth.h" + +G_BEGIN_DECLS + +GType gst_rtsp_token_get_type(void); + +#define GST_TYPE_RTSP_TOKEN (gst_rtsp_token_get_type()) +#define GST_IS_RTSP_TOKEN(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_RTSP_TOKEN)) +#define GST_RTSP_TOKEN_CAST(obj) ((GstRTSPToken*)(obj)) +#define GST_RTSP_TOKEN(obj) (GST_RTSP_TOKEN_CAST(obj)) + +/** + * GstRTSPToken: + * + * An opaque object used for checking authorisations. + * It is generated after successful authentication. + */ +struct _GstRTSPToken { + GstMiniObject mini_object; +}; + +/* refcounting */ +/** + * gst_rtsp_token_ref: + * @token: The token to refcount + * + * Increase the refcount of this token. + * + * Returns: (transfer full): @token (for convenience when doing assignments) + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC GstRTSPToken * gst_rtsp_token_ref (GstRTSPToken * token); +#endif + +static inline GstRTSPToken * +gst_rtsp_token_ref (GstRTSPToken * token) +{ + return (GstRTSPToken *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (token)); +} + +/** + * gst_rtsp_token_unref: + * @token: (transfer full): the token to refcount + * + * Decrease the refcount of an token, freeing it if the refcount reaches 0. + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC void gst_rtsp_token_unref (GstRTSPToken * token); +#endif + +static inline void +gst_rtsp_token_unref (GstRTSPToken * token) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (token)); +} + + +GstRTSPToken * gst_rtsp_token_new_empty (void); +GstRTSPToken * gst_rtsp_token_new (const gchar * firstfield, ...); +GstRTSPToken * gst_rtsp_token_new_valist (const gchar * firstfield, va_list var_args); + +const GstStructure * gst_rtsp_token_get_structure (GstRTSPToken *token); +GstStructure * gst_rtsp_token_writable_structure (GstRTSPToken *token); + +const gchar * gst_rtsp_token_get_string (GstRTSPToken *token, + const gchar *field); +gboolean gst_rtsp_token_is_allowed (GstRTSPToken *token, + const gchar *field); +G_END_DECLS + +#endif /* __GST_RTSP_TOKEN_H__ */ diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec new file mode 100644 index 0000000..7d47de6 --- /dev/null +++ b/packaging/gst-rtsp-server.spec @@ -0,0 +1,73 @@ +Name: gst-rtsp-server +Summary: Multimedia Framework Library +Version: 1.4.5 +Release: 3 +Group: System/Libraries +License: LGPL-2.0+ +Source0: %{name}-%{version}.tar.gz +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +BuildRequires: pkgconfig(gstreamer-1.0) +BuildRequires: pkgconfig(gstreamer-plugins-base-1.0) + +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%description + +%package devel +Summary: Multimedia Framework RTSP server library (DEV) +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel + +%package factory +Summary: Multimedia Framework RTSP server Library (Factory) +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description factory + +%prep +%setup -q + +%build + +./autogen.sh + +CFLAGS+=" -DEXPORT_API=\"__attribute__((visibility(\\\"default\\\")))\" "; export CFLAGS +LDFLAGS+="-Wl,--rpath=%{_prefix}/lib -Wl,--hash-style=both -Wl,--as-needed"; export LDFLAGS + +# always enable sdk build. This option should go away +%configure --disable-static + +# Call make instruction with smp support +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install +mkdir -p %{buildroot}/%{_datadir}/license +cp -rf %{_builddir}/%{name}-%{version}/COPYING %{buildroot}%{_datadir}/license/%{name} + +%clean +rm -rf %{buildroot} + +%post +/sbin/ldconfig + +%postun +/sbin/ldconfig + +%files +%manifest gst-rtsp-server.manifest +%defattr(-,root,root,-) +%{_datadir}/license/%{name} +%{_libdir}/*.so.* + +%files devel +%defattr(-,root,root,-) +%{_libdir}/*.so +%{_includedir}/gstreamer-1.0/gst/rtsp-server/rtsp-*.h +%{_includedir}/gstreamer-1.0/gst/rtsp-server/gstwfd*.h +%{_libdir}/pkgconfig/* diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am new file mode 100644 index 0000000..c45755e --- /dev/null +++ b/pkgconfig/Makefile.am @@ -0,0 +1,21 @@ +pcfiles = \ + gstreamer-rtsp-server-@GST_API_VERSION@.pc + +pcfiles_uninstalled = \ + gstreamer-rtsp-server-@GST_API_VERSION@-uninstalled.pc + +all-local: $(pcfiles) $(pcfiles_uninstalled) + +### how to generate pc files +%-@GST_API_VERSION@.pc: %.pc + cp $< $@ +%-@GST_API_VERSION@-uninstalled.pc: %-uninstalled.pc + cp $< $@ + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pcfiles) + +EXTRA_DIST = \ + gstreamer-rtsp-server.pc.in \ + gstreamer-rtsp-server-uninstalled.pc.in +CLEANFILES = $(pcfiles) $(pcfiles_uninstalled) diff --git a/pkgconfig/Makefile.in b/pkgconfig/Makefile.in new file mode 100644 index 0000000..bafc540 --- /dev/null +++ b/pkgconfig/Makefile.in @@ -0,0 +1,637 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = pkgconfig +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(srcdir)/gstreamer-rtsp-server.pc.in \ + $(srcdir)/gstreamer-rtsp-server-uninstalled.pc.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-docbook.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-default.m4 \ + $(top_srcdir)/common/m4/gst-doc.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = gstreamer-rtsp-server.pc \ + gstreamer-rtsp-server-uninstalled.pc +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" +DATA = $(pkgconfig_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAT_ENTRY_END = @CAT_ENTRY_END@ +CAT_ENTRY_START = @CAT_ENTRY_START@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@ +DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@ +DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@ +DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@ +DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ = @GLIB_REQ@ +GREP = @GREP@ +GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@ +GSTPD_PLUGINS_DIR = @GSTPD_PLUGINS_DIR@ +GSTPG_PLUGINS_DIR = @GSTPG_PLUGINS_DIR@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_BASE_CFLAGS = @GST_BASE_CFLAGS@ +GST_BASE_LIBS = @GST_BASE_LIBS@ +GST_CFLAGS = @GST_CFLAGS@ +GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@ +GST_CHECK_LIBS = @GST_CHECK_LIBS@ +GST_CURRENT = @GST_CURRENT@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBS = @GST_LIBS@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGINS_BAD_CFLAGS = @GST_PLUGINS_BAD_CFLAGS@ +GST_PLUGINS_BAD_DIR = @GST_PLUGINS_BAD_DIR@ +GST_PLUGINS_BAD_LIBS = @GST_PLUGINS_BAD_LIBS@ +GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@ +GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@ +GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@ +GST_PLUGINS_DIR = @GST_PLUGINS_DIR@ +GST_PLUGINS_GOOD_CFLAGS = @GST_PLUGINS_GOOD_CFLAGS@ +GST_PLUGINS_GOOD_DIR = @GST_PLUGINS_GOOD_DIR@ +GST_PLUGINS_GOOD_LIBS = @GST_PLUGINS_GOOD_LIBS@ +GST_REVISION = @GST_REVISION@ +GST_TOOLS_DIR = @GST_TOOLS_DIR@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ +HAVE_DVIPS = @HAVE_DVIPS@ +HAVE_EPSTOPDF = @HAVE_EPSTOPDF@ +HAVE_JADETEX = @HAVE_JADETEX@ +HAVE_PNGTOPNM = @HAVE_PNGTOPNM@ +HAVE_PNMTOPS = @HAVE_PNMTOPS@ +HAVE_PS2PDF = @HAVE_PS2PDF@ +HAVE_XMLLINT = @HAVE_XMLLINT@ +HAVE_XSLTPROC = @HAVE_XSLTPROC@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCGROUP_CFLAGS = @LIBCGROUP_CFLAGS@ +LIBCGROUP_LIBS = @LIBCGROUP_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +XML_CATALOG = @XML_CATALOG@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pcfiles = \ + gstreamer-rtsp-server-@GST_API_VERSION@.pc + +pcfiles_uninstalled = \ + gstreamer-rtsp-server-@GST_API_VERSION@-uninstalled.pc + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pcfiles) +EXTRA_DIST = \ + gstreamer-rtsp-server.pc.in \ + gstreamer-rtsp-server-uninstalled.pc.in + +CLEANFILES = $(pcfiles) $(pcfiles_uninstalled) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu pkgconfig/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu pkgconfig/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +gstreamer-rtsp-server.pc: $(top_builddir)/config.status $(srcdir)/gstreamer-rtsp-server.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gstreamer-rtsp-server-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/gstreamer-rtsp-server-uninstalled.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) all-local +installdirs: + for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkgconfigDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkgconfigDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool cscopelist-am ctags-am distclean \ + distclean-generic distclean-libtool distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pkgconfigDATA install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-pkgconfigDATA + + +all-local: $(pcfiles) $(pcfiles_uninstalled) + +### how to generate pc files +%-@GST_API_VERSION@.pc: %.pc + cp $< $@ +%-@GST_API_VERSION@-uninstalled.pc: %-uninstalled.pc + cp $< $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pkgconfig/gstreamer-rtsp-server-uninstalled.pc.in b/pkgconfig/gstreamer-rtsp-server-uninstalled.pc.in new file mode 100644 index 0000000..e453805 --- /dev/null +++ b/pkgconfig/gstreamer-rtsp-server-uninstalled.pc.in @@ -0,0 +1,12 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir=${pcfiledir}/../gst/rtsp-server +includedir=${pcfiledir}/.. + +Name: gst-rtsp-server +Description: GStreamer based RTSP server +Version: @VERSION@ +Requires: gstreamer-@GST_API_VERSION@ gstreamer-plugins-base-@GST_API_VERSION@ +Libs: ${libdir}/libgstrtspserver-@GST_API_VERSION@.la +Cflags: -I${includedir} -I@srcdir@/.. diff --git a/pkgconfig/gstreamer-rtsp-server.pc.in b/pkgconfig/gstreamer-rtsp-server.pc.in new file mode 100644 index 0000000..3a1d820 --- /dev/null +++ b/pkgconfig/gstreamer-rtsp-server.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_API_VERSION@ + +Name: gst-rtsp-server +Description: GStreamer based RTSP server +Version: @VERSION@ +Requires: gstreamer-@GST_API_VERSION@ gstreamer-base-@GST_API_VERSION@ +Libs: -L${libdir} -lgstrtspserver-@GST_API_VERSION@ +Cflags: -I${includedir} diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..ca2ba66 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,19 @@ +noinst_PROGRAMS = test-cleanup test-reuse + +AM_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) +AM_LDFLAGS = \ + $(GST_LIBS) \ + $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la + +if BUILD_TESTS +SUBDIRS_CHECK = check +else +SUBDIRS_CHECK = +endif + +SUBDIRS = \ + $(SUBDIRS_CHECK) + +DIST_SUBDIRS = \ + check diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 0000000..63678e5 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,840 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = test-cleanup$(EXEEXT) test-reuse$(EXEEXT) +subdir = tests +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-docbook.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-default.m4 \ + $(top_srcdir)/common/m4/gst-doc.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +test_cleanup_SOURCES = test-cleanup.c +test_cleanup_OBJECTS = test-cleanup.$(OBJEXT) +test_cleanup_LDADD = $(LDADD) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +test_reuse_SOURCES = test-reuse.c +test_reuse_OBJECTS = test-reuse.$(OBJEXT) +test_reuse_LDADD = $(LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = test-cleanup.c test-reuse.c +DIST_SOURCES = test-cleanup.c test-reuse.c +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAT_ENTRY_END = @CAT_ENTRY_END@ +CAT_ENTRY_START = @CAT_ENTRY_START@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@ +DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@ +DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@ +DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@ +DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ = @GLIB_REQ@ +GREP = @GREP@ +GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@ +GSTPD_PLUGINS_DIR = @GSTPD_PLUGINS_DIR@ +GSTPG_PLUGINS_DIR = @GSTPG_PLUGINS_DIR@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_BASE_CFLAGS = @GST_BASE_CFLAGS@ +GST_BASE_LIBS = @GST_BASE_LIBS@ +GST_CFLAGS = @GST_CFLAGS@ +GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@ +GST_CHECK_LIBS = @GST_CHECK_LIBS@ +GST_CURRENT = @GST_CURRENT@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBS = @GST_LIBS@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGINS_BAD_CFLAGS = @GST_PLUGINS_BAD_CFLAGS@ +GST_PLUGINS_BAD_DIR = @GST_PLUGINS_BAD_DIR@ +GST_PLUGINS_BAD_LIBS = @GST_PLUGINS_BAD_LIBS@ +GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@ +GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@ +GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@ +GST_PLUGINS_DIR = @GST_PLUGINS_DIR@ +GST_PLUGINS_GOOD_CFLAGS = @GST_PLUGINS_GOOD_CFLAGS@ +GST_PLUGINS_GOOD_DIR = @GST_PLUGINS_GOOD_DIR@ +GST_PLUGINS_GOOD_LIBS = @GST_PLUGINS_GOOD_LIBS@ +GST_REVISION = @GST_REVISION@ +GST_TOOLS_DIR = @GST_TOOLS_DIR@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ +HAVE_DVIPS = @HAVE_DVIPS@ +HAVE_EPSTOPDF = @HAVE_EPSTOPDF@ +HAVE_JADETEX = @HAVE_JADETEX@ +HAVE_PNGTOPNM = @HAVE_PNGTOPNM@ +HAVE_PNMTOPS = @HAVE_PNMTOPS@ +HAVE_PS2PDF = @HAVE_PS2PDF@ +HAVE_XMLLINT = @HAVE_XMLLINT@ +HAVE_XSLTPROC = @HAVE_XSLTPROC@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCGROUP_CFLAGS = @LIBCGROUP_CFLAGS@ +LIBCGROUP_LIBS = @LIBCGROUP_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +XML_CATALOG = @XML_CATALOG@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) +AM_LDFLAGS = \ + $(GST_LIBS) \ + $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la + +@BUILD_TESTS_FALSE@SUBDIRS_CHECK = +@BUILD_TESTS_TRUE@SUBDIRS_CHECK = check +SUBDIRS = \ + $(SUBDIRS_CHECK) + +DIST_SUBDIRS = \ + check + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-cleanup$(EXEEXT): $(test_cleanup_OBJECTS) $(test_cleanup_DEPENDENCIES) $(EXTRA_test_cleanup_DEPENDENCIES) + @rm -f test-cleanup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_cleanup_OBJECTS) $(test_cleanup_LDADD) $(LIBS) + +test-reuse$(EXEEXT): $(test_reuse_OBJECTS) $(test_reuse_DEPENDENCIES) $(EXTRA_test_reuse_DEPENDENCIES) + @rm -f test-reuse$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_reuse_OBJECTS) $(test_reuse_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-cleanup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-reuse.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool \ + clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am new file mode 100644 index 0000000..82e6d42 --- /dev/null +++ b/tests/check/Makefile.am @@ -0,0 +1,62 @@ +include $(top_srcdir)/common/check.mak + +CHECK_REGISTRY = $(top_builddir)/tests/check/test-registry.reg +TEST_FILES_DIRECTORY = $(top_srcdir)/tests/files + +REGISTRY_ENVIRONMENT = \ + GST_REGISTRY_1_0=$(CHECK_REGISTRY) + +TESTS_ENVIRONMENT = \ + CK_DEFAULT_TIMEOUT=120 \ + GST_STATE_IGNORE_ELEMENTS="$(STATE_IGNORE_ELEMENTS)" \ + $(REGISTRY_ENVIRONMENT) \ + GST_PLUGIN_SYSTEM_PATH_1_0= \ + GST_PLUGIN_PATH_1_0=$(GST_PLUGINS_DIR):$(GSTPB_PLUGINS_DIR):$(GSTPG_PLUGINS_DIR):$(GSTPD_PLUGINS_DIR) \ + GST_PLUGIN_LOADING_WHITELIST="gstreamer:gst-plugins-base:gst-plugins-good:gst-plugins-bad" + + +# ths core dumps of some machines have PIDs appended +CLEANFILES = core.* test-registry.* + +clean-local: clean-local-check + +$(CHECK_REGISTRY): + $(TESTS_ENVIRONMENT) + +TESTS = $(check_PROGRAMS) + +check_PROGRAMS = \ + gst/rtspserver \ + gst/client \ + gst/mountpoints \ + gst/mediafactory \ + gst/media \ + gst/stream \ + gst/addresspool \ + gst/threadpool \ + gst/permissions \ + gst/token \ + gst/sessionmedia \ + gst/sessionpool + +# these tests don't even pass +noinst_PROGRAMS = + +AM_CFLAGS = -I$(top_srcdir)/gst/rtsp-server \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(GIO_CFLAGS) \ + $(GST_CFLAGS) \ + $(GST_CHECK_CFLAGS) \ + -DGST_TEST_FILES_PATH="\"$(TEST_FILES_DIRECTORY)\"" \ + -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS +AM_CXXFLAGS = $(GST_CXXFLAGS) $(GST_CHECK_CFLAGS) \ + -DGST_TEST_FILES_PATH="\"$(TEST_FILES_DIRECTORY)\"" \ + -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS +LDADD = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_API_VERSION@ \ + -lgstrtsp-@GST_API_VERSION@ -lgstsdp-@GST_API_VERSION@ \ + $(GST_BASE_LIBS) $(GIO_LIBS) \ + $(GST_LIBS) $(GST_CHECK_LIBS) $(GST_RTSP_SERVER_LIBS) + +SUPPRESSIONS = $(top_srcdir)/common/gst.supp diff --git a/tests/check/Makefile.in b/tests/check/Makefile.in new file mode 100644 index 0000000..a68c6ca --- /dev/null +++ b/tests/check/Makefile.in @@ -0,0 +1,1635 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +DIST_COMMON = $(top_srcdir)/common/check.mak $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.am $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +check_PROGRAMS = gst/rtspserver$(EXEEXT) gst/client$(EXEEXT) \ + gst/mountpoints$(EXEEXT) gst/mediafactory$(EXEEXT) \ + gst/media$(EXEEXT) gst/stream$(EXEEXT) \ + gst/addresspool$(EXEEXT) gst/threadpool$(EXEEXT) \ + gst/permissions$(EXEEXT) gst/token$(EXEEXT) \ + gst/sessionmedia$(EXEEXT) gst/sessionpool$(EXEEXT) +noinst_PROGRAMS = +subdir = tests/check +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-docbook.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-default.m4 \ + $(top_srcdir)/common/m4/gst-doc.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +gst_addresspool_SOURCES = gst/addresspool.c +am__dirstamp = $(am__leading_dot)dirstamp +gst_addresspool_OBJECTS = gst/addresspool.$(OBJEXT) +gst_addresspool_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +gst_addresspool_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +gst_client_SOURCES = gst/client.c +gst_client_OBJECTS = gst/client.$(OBJEXT) +gst_client_LDADD = $(LDADD) +gst_client_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +gst_media_SOURCES = gst/media.c +gst_media_OBJECTS = gst/media.$(OBJEXT) +gst_media_LDADD = $(LDADD) +gst_media_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +gst_mediafactory_SOURCES = gst/mediafactory.c +gst_mediafactory_OBJECTS = gst/mediafactory.$(OBJEXT) +gst_mediafactory_LDADD = $(LDADD) +gst_mediafactory_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +gst_mountpoints_SOURCES = gst/mountpoints.c +gst_mountpoints_OBJECTS = gst/mountpoints.$(OBJEXT) +gst_mountpoints_LDADD = $(LDADD) +gst_mountpoints_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +gst_permissions_SOURCES = gst/permissions.c +gst_permissions_OBJECTS = gst/permissions.$(OBJEXT) +gst_permissions_LDADD = $(LDADD) +gst_permissions_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +gst_rtspserver_SOURCES = gst/rtspserver.c +gst_rtspserver_OBJECTS = gst/rtspserver.$(OBJEXT) +gst_rtspserver_LDADD = $(LDADD) +gst_rtspserver_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +gst_sessionmedia_SOURCES = gst/sessionmedia.c +gst_sessionmedia_OBJECTS = gst/sessionmedia.$(OBJEXT) +gst_sessionmedia_LDADD = $(LDADD) +gst_sessionmedia_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +gst_sessionpool_SOURCES = gst/sessionpool.c +gst_sessionpool_OBJECTS = gst/sessionpool.$(OBJEXT) +gst_sessionpool_LDADD = $(LDADD) +gst_sessionpool_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +gst_stream_SOURCES = gst/stream.c +gst_stream_OBJECTS = gst/stream.$(OBJEXT) +gst_stream_LDADD = $(LDADD) +gst_stream_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +gst_threadpool_SOURCES = gst/threadpool.c +gst_threadpool_OBJECTS = gst/threadpool.$(OBJEXT) +gst_threadpool_LDADD = $(LDADD) +gst_threadpool_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +gst_token_SOURCES = gst/token.c +gst_token_OBJECTS = gst/token.$(OBJEXT) +gst_token_LDADD = $(LDADD) +gst_token_DEPENDENCIES = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = gst/addresspool.c gst/client.c gst/media.c \ + gst/mediafactory.c gst/mountpoints.c gst/permissions.c \ + gst/rtspserver.c gst/sessionmedia.c gst/sessionpool.c \ + gst/stream.c gst/threadpool.c gst/token.c +DIST_SOURCES = gst/addresspool.c gst/client.c gst/media.c \ + gst/mediafactory.c gst/mountpoints.c gst/permissions.c \ + gst/rtspserver.c gst/sessionmedia.c gst/sessionpool.c \ + gst/stream.c gst/threadpool.c gst/token.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAT_ENTRY_END = @CAT_ENTRY_END@ +CAT_ENTRY_START = @CAT_ENTRY_START@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@ +DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@ +DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@ +DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@ +DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ = @GLIB_REQ@ +GREP = @GREP@ +GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@ +GSTPD_PLUGINS_DIR = @GSTPD_PLUGINS_DIR@ +GSTPG_PLUGINS_DIR = @GSTPG_PLUGINS_DIR@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_BASE_CFLAGS = @GST_BASE_CFLAGS@ +GST_BASE_LIBS = @GST_BASE_LIBS@ +GST_CFLAGS = @GST_CFLAGS@ +GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@ +GST_CHECK_LIBS = @GST_CHECK_LIBS@ +GST_CURRENT = @GST_CURRENT@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBS = @GST_LIBS@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGINS_BAD_CFLAGS = @GST_PLUGINS_BAD_CFLAGS@ +GST_PLUGINS_BAD_DIR = @GST_PLUGINS_BAD_DIR@ +GST_PLUGINS_BAD_LIBS = @GST_PLUGINS_BAD_LIBS@ +GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@ +GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@ +GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@ +GST_PLUGINS_DIR = @GST_PLUGINS_DIR@ +GST_PLUGINS_GOOD_CFLAGS = @GST_PLUGINS_GOOD_CFLAGS@ +GST_PLUGINS_GOOD_DIR = @GST_PLUGINS_GOOD_DIR@ +GST_PLUGINS_GOOD_LIBS = @GST_PLUGINS_GOOD_LIBS@ +GST_REVISION = @GST_REVISION@ +GST_TOOLS_DIR = @GST_TOOLS_DIR@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ +HAVE_DVIPS = @HAVE_DVIPS@ +HAVE_EPSTOPDF = @HAVE_EPSTOPDF@ +HAVE_JADETEX = @HAVE_JADETEX@ +HAVE_PNGTOPNM = @HAVE_PNGTOPNM@ +HAVE_PNMTOPS = @HAVE_PNMTOPS@ +HAVE_PS2PDF = @HAVE_PS2PDF@ +HAVE_XMLLINT = @HAVE_XMLLINT@ +HAVE_XSLTPROC = @HAVE_XSLTPROC@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCGROUP_CFLAGS = @LIBCGROUP_CFLAGS@ +LIBCGROUP_LIBS = @LIBCGROUP_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +XML_CATALOG = @XML_CATALOG@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# inspect every plugin feature +GST_INSPECT = $(GST_TOOLS_DIR)/gst-inspect-$(GST_API_VERSION) +CHECK_REGISTRY = $(top_builddir)/tests/check/test-registry.reg +TEST_FILES_DIRECTORY = $(top_srcdir)/tests/files +REGISTRY_ENVIRONMENT = \ + GST_REGISTRY_1_0=$(CHECK_REGISTRY) + +TESTS_ENVIRONMENT = \ + CK_DEFAULT_TIMEOUT=120 \ + GST_STATE_IGNORE_ELEMENTS="$(STATE_IGNORE_ELEMENTS)" \ + $(REGISTRY_ENVIRONMENT) \ + GST_PLUGIN_SYSTEM_PATH_1_0= \ + GST_PLUGIN_PATH_1_0=$(GST_PLUGINS_DIR):$(GSTPB_PLUGINS_DIR):$(GSTPG_PLUGINS_DIR):$(GSTPD_PLUGINS_DIR) \ + GST_PLUGIN_LOADING_WHITELIST="gstreamer:gst-plugins-base:gst-plugins-good:gst-plugins-bad" + + +# ths core dumps of some machines have PIDs appended +CLEANFILES = core.* test-registry.* +TESTS = $(check_PROGRAMS) +AM_CFLAGS = -I$(top_srcdir)/gst/rtsp-server \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(GIO_CFLAGS) \ + $(GST_CFLAGS) \ + $(GST_CHECK_CFLAGS) \ + -DGST_TEST_FILES_PATH="\"$(TEST_FILES_DIRECTORY)\"" \ + -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS + +AM_CXXFLAGS = $(GST_CXXFLAGS) $(GST_CHECK_CFLAGS) \ + -DGST_TEST_FILES_PATH="\"$(TEST_FILES_DIRECTORY)\"" \ + -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS + +LDADD = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \ + $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_API_VERSION@ \ + -lgstrtsp-@GST_API_VERSION@ -lgstsdp-@GST_API_VERSION@ \ + $(GST_BASE_LIBS) $(GIO_LIBS) \ + $(GST_LIBS) $(GST_CHECK_LIBS) $(GST_RTSP_SERVER_LIBS) + +SUPPRESSIONS = $(top_srcdir)/common/gst.supp +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common/check.mak $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/check/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/check/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/common/check.mak: + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +gst/$(am__dirstamp): + @$(MKDIR_P) gst + @: > gst/$(am__dirstamp) +gst/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) gst/$(DEPDIR) + @: > gst/$(DEPDIR)/$(am__dirstamp) +gst/addresspool.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/addresspool$(EXEEXT): $(gst_addresspool_OBJECTS) $(gst_addresspool_DEPENDENCIES) $(EXTRA_gst_addresspool_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/addresspool$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_addresspool_OBJECTS) $(gst_addresspool_LDADD) $(LIBS) +gst/client.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/client$(EXEEXT): $(gst_client_OBJECTS) $(gst_client_DEPENDENCIES) $(EXTRA_gst_client_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/client$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_client_OBJECTS) $(gst_client_LDADD) $(LIBS) +gst/media.$(OBJEXT): gst/$(am__dirstamp) gst/$(DEPDIR)/$(am__dirstamp) + +gst/media$(EXEEXT): $(gst_media_OBJECTS) $(gst_media_DEPENDENCIES) $(EXTRA_gst_media_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/media$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_media_OBJECTS) $(gst_media_LDADD) $(LIBS) +gst/mediafactory.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/mediafactory$(EXEEXT): $(gst_mediafactory_OBJECTS) $(gst_mediafactory_DEPENDENCIES) $(EXTRA_gst_mediafactory_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/mediafactory$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_mediafactory_OBJECTS) $(gst_mediafactory_LDADD) $(LIBS) +gst/mountpoints.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/mountpoints$(EXEEXT): $(gst_mountpoints_OBJECTS) $(gst_mountpoints_DEPENDENCIES) $(EXTRA_gst_mountpoints_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/mountpoints$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_mountpoints_OBJECTS) $(gst_mountpoints_LDADD) $(LIBS) +gst/permissions.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/permissions$(EXEEXT): $(gst_permissions_OBJECTS) $(gst_permissions_DEPENDENCIES) $(EXTRA_gst_permissions_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/permissions$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_permissions_OBJECTS) $(gst_permissions_LDADD) $(LIBS) +gst/rtspserver.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/rtspserver$(EXEEXT): $(gst_rtspserver_OBJECTS) $(gst_rtspserver_DEPENDENCIES) $(EXTRA_gst_rtspserver_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/rtspserver$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_rtspserver_OBJECTS) $(gst_rtspserver_LDADD) $(LIBS) +gst/sessionmedia.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/sessionmedia$(EXEEXT): $(gst_sessionmedia_OBJECTS) $(gst_sessionmedia_DEPENDENCIES) $(EXTRA_gst_sessionmedia_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/sessionmedia$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_sessionmedia_OBJECTS) $(gst_sessionmedia_LDADD) $(LIBS) +gst/sessionpool.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/sessionpool$(EXEEXT): $(gst_sessionpool_OBJECTS) $(gst_sessionpool_DEPENDENCIES) $(EXTRA_gst_sessionpool_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/sessionpool$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_sessionpool_OBJECTS) $(gst_sessionpool_LDADD) $(LIBS) +gst/stream.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/stream$(EXEEXT): $(gst_stream_OBJECTS) $(gst_stream_DEPENDENCIES) $(EXTRA_gst_stream_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/stream$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_stream_OBJECTS) $(gst_stream_LDADD) $(LIBS) +gst/threadpool.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/threadpool$(EXEEXT): $(gst_threadpool_OBJECTS) $(gst_threadpool_DEPENDENCIES) $(EXTRA_gst_threadpool_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/threadpool$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_threadpool_OBJECTS) $(gst_threadpool_LDADD) $(LIBS) +gst/token.$(OBJEXT): gst/$(am__dirstamp) gst/$(DEPDIR)/$(am__dirstamp) + +gst/token$(EXEEXT): $(gst_token_OBJECTS) $(gst_token_DEPENDENCIES) $(EXTRA_gst_token_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/token$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_token_OBJECTS) $(gst_token_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f gst/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/addresspool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/client.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/media.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/mediafactory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/mountpoints.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/permissions.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/rtspserver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/sessionmedia.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/sessionpool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/stream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/threadpool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/token.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf gst/.libs gst/_libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + else \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +gst/rtspserver.log: gst/rtspserver$(EXEEXT) + @p='gst/rtspserver$(EXEEXT)'; \ + b='gst/rtspserver'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/client.log: gst/client$(EXEEXT) + @p='gst/client$(EXEEXT)'; \ + b='gst/client'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/mountpoints.log: gst/mountpoints$(EXEEXT) + @p='gst/mountpoints$(EXEEXT)'; \ + b='gst/mountpoints'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/mediafactory.log: gst/mediafactory$(EXEEXT) + @p='gst/mediafactory$(EXEEXT)'; \ + b='gst/mediafactory'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/media.log: gst/media$(EXEEXT) + @p='gst/media$(EXEEXT)'; \ + b='gst/media'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/stream.log: gst/stream$(EXEEXT) + @p='gst/stream$(EXEEXT)'; \ + b='gst/stream'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/addresspool.log: gst/addresspool$(EXEEXT) + @p='gst/addresspool$(EXEEXT)'; \ + b='gst/addresspool'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/threadpool.log: gst/threadpool$(EXEEXT) + @p='gst/threadpool$(EXEEXT)'; \ + b='gst/threadpool'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/permissions.log: gst/permissions$(EXEEXT) + @p='gst/permissions$(EXEEXT)'; \ + b='gst/permissions'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/token.log: gst/token$(EXEEXT) + @p='gst/token$(EXEEXT)'; \ + b='gst/token'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/sessionmedia.log: gst/sessionmedia$(EXEEXT) + @p='gst/sessionmedia$(EXEEXT)'; \ + b='gst/sessionmedia'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/sessionpool.log: gst/sessionpool$(EXEEXT) + @p='gst/sessionpool$(EXEEXT)'; \ + b='gst/sessionpool'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f gst/$(DEPDIR)/$(am__dirstamp) + -rm -f gst/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf gst/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf gst/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool clean-local \ + clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am recheck tags tags-am uninstall \ + uninstall-am + + +# keep target around, since it's referenced in the modules' Makefiles +clean-local-check: + @echo + +# hangs spectacularly on some machines, so let's not do this by default yet +@HAVE_VALGRIND_TRUE@check-valgrind: +@HAVE_VALGRIND_TRUE@ $(MAKE) valgrind +@HAVE_VALGRIND_FALSE@check-valgrind: +@HAVE_VALGRIND_FALSE@ @true + +LOOPS ?= 10 + +# run any given test by running make test.check +# if the test fails, run it again at at least debug level 2 +%.check: % + @$(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=20 \ + $* || \ + $(TESTS_ENVIRONMENT) \ + GST_DEBUG=$$GST_DEBUG,*:2 \ + CK_DEFAULT_TIMEOUT=20 \ + $* + +# just like 'check', but don't run it again if it fails (useful for debugging) +%.check-norepeat: % + @$(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=20 \ + $* + +# run any given test in a loop +%.torture: % + @for i in `seq 1 $(LOOPS)`; do \ + $(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=20 \ + $*; done + +# run any given test in an infinite loop +%.forever: % + @while true; do \ + $(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=20 \ + $* || break; done + +# valgrind any given test by running make test.valgrind +%.valgrind: % + @$(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=360 \ + G_SLICE=always-malloc \ + $(LIBTOOL) --mode=execute \ + $(VALGRIND_PATH) -q \ + $(foreach s,$(SUPPRESSIONS),--suppressions=$(s)) \ + --tool=memcheck --leak-check=full --trace-children=yes \ + --show-possibly-lost=no \ + --leak-resolution=high --num-callers=20 \ + ./$* 2>&1 | tee valgrind.log + @if grep "==" valgrind.log > /dev/null 2>&1; then \ + rm valgrind.log; \ + exit 1; \ + fi + @rm valgrind.log + +# valgrind any given test and generate suppressions for it +%.valgrind.gen-suppressions: % + @$(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=360 \ + G_SLICE=always-malloc \ + $(LIBTOOL) --mode=execute \ + $(VALGRIND_PATH) -q \ + $(foreach s,$(SUPPRESSIONS),--suppressions=$(s)) \ + --tool=memcheck --leak-check=full --trace-children=yes \ + --show-possibly-lost=no \ + --leak-resolution=high --num-callers=20 \ + --gen-suppressions=all \ + ./$* 2>&1 | tee suppressions.log + +# valgrind torture any given test +%.valgrind-torture: % + @for i in `seq 1 $(LOOPS)`; do \ + $(MAKE) $*.valgrind || \ + (echo "Failure after $$i runs"; exit 1) || \ + exit 1; \ + done + @banner="All $(LOOPS) loops passed"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo $$dashes; echo $$banner; echo $$dashes + +# valgrind any given test until failure by running make test.valgrind-forever +%.valgrind-forever: % + @while $(MAKE) $*.valgrind; do \ + true; done + +# gdb any given test by running make test.gdb +%.gdb: % + @$(TESTS_ENVIRONMENT) \ + CK_FORK=no \ + $(LIBTOOL) --mode=execute \ + gdb $* + +%.lcov-reset: + $(MAKE) $*.lcov-run + $(MAKE) $*.lcov-report + +%.lcov: % + $(MAKE) $*.lcov-reset + +@GST_GCOV_ENABLED_TRUE@%.lcov-clean: +@GST_GCOV_ENABLED_TRUE@ $(MAKE) -C $(top_builddir) lcov-clean + +@GST_GCOV_ENABLED_TRUE@%.lcov-run: +@GST_GCOV_ENABLED_TRUE@ $(MAKE) $*.lcov-clean +@GST_GCOV_ENABLED_TRUE@ $(MAKE) $*.check + +@GST_GCOV_ENABLED_TRUE@%.lcov-report: +@GST_GCOV_ENABLED_TRUE@ $(MAKE) -C $(top_builddir) lcov-report +@GST_GCOV_ENABLED_FALSE@%.lcov-run: +@GST_GCOV_ENABLED_FALSE@ echo "Need to reconfigure with --enable-gcov" + +@GST_GCOV_ENABLED_FALSE@%.lcov-report: +@GST_GCOV_ENABLED_FALSE@ echo "Need to reconfigure with --enable-gcov" + +# torture tests +torture: $(TESTS) + -rm test-registry.* + @echo "Torturing tests ..." + @for i in `seq 1 $(LOOPS)`; do \ + $(MAKE) check || \ + (echo "Failure after $$i runs"; exit 1) || \ + exit 1; \ + done + @banner="All $(LOOPS) loops passed"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo $$dashes; echo $$banner; echo $$dashes + +# forever tests +forever: $(TESTS) + -rm test-registry.* + @echo "Forever tests ..." + @while true; do \ + $(MAKE) check || \ + (echo "Failure"; exit 1) || \ + exit 1; \ + done + +# valgrind all tests +valgrind: $(TESTS) + @echo "Valgrinding tests ..." + @failed=0; \ + for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(TESTS)); do \ + $(MAKE) $$t.valgrind; \ + if test "$$?" -ne 0; then \ + echo "Valgrind error for test $$t"; \ + failed=`expr $$failed + 1`; \ + whicht="$$whicht $$t"; \ + fi; \ + done; \ + if test "$$failed" -ne 0; then \ + echo "$$failed tests had leaks or errors under valgrind:"; \ + echo "$$whicht"; \ + false; \ + fi + +# valgrind all tests until failure +valgrind-forever: $(TESTS) + -rm test-registry.* + @echo "Forever valgrinding tests ..." + @while true; do \ + $(MAKE) valgrind || \ + (echo "Failure"; exit 1) || \ + exit 1; \ + done + +# valgrind torture all tests +valgrind-torture: $(TESTS) + -rm test-registry.* + @echo "Torturing and valgrinding tests ..." + @for i in `seq 1 $(LOOPS)`; do \ + $(MAKE) valgrind || \ + (echo "Failure after $$i runs"; exit 1) || \ + exit 1; \ + done + @banner="All $(LOOPS) loops passed"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo $$dashes; echo $$banner; echo $$dashes + +# valgrind all tests and generate suppressions +valgrind.gen-suppressions: $(TESTS) + @echo "Valgrinding tests ..." + @failed=0; \ + for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(TESTS)); do \ + $(MAKE) $$t.valgrind.gen-suppressions; \ + if test "$$?" -ne 0; then \ + echo "Valgrind error for test $$t"; \ + failed=`expr $$failed + 1`; \ + whicht="$$whicht $$t"; \ + fi; \ + done; \ + if test "$$failed" -ne 0; then \ + echo "$$failed tests had leaks or errors under valgrind:"; \ + echo "$$whicht"; \ + false; \ + fi +inspect: + @echo "Inspecting features ..." + @for e in `$(TESTS_ENVIRONMENT) $(GST_INSPECT) | head -n -2 \ + | cut -d: -f2`; \ + do echo Inspecting $$e; \ + $(GST_INSPECT) $$e > /dev/null 2>&1; done + +help: + @echo + @echo "make check -- run all checks" + @echo "make torture -- run all checks $(LOOPS) times" + @echo "make (dir)/(test).check -- run the given check once, repeat with GST_DEBUG=*:2 if it fails" + @echo "make (dir)/(test).check-norepeat -- run the given check once, but don't run it again if it fails" + @echo "make (dir)/(test).forever -- run the given check forever" + @echo "make (dir)/(test).torture -- run the given check $(LOOPS) times" + @echo + @echo "make (dir)/(test).gdb -- start up gdb for the given test" + @echo + @echo "make valgrind -- valgrind all tests" + @echo "make valgrind-forever -- valgrind all tests forever" + @echo "make valgrind-torture -- valgrind all tests $(LOOPS) times" + @echo "make valgrind.gen-suppressions -- generate suppressions for all tests" + @echo " and save to suppressions.log" + @echo "make (dir)/(test).valgrind -- valgrind the given test" + @echo "make (dir)/(test).valgrind-forever -- valgrind the given test forever" + @echo "make (dir)/(test).valgrind-torture -- valgrind the given test $(LOOPS) times" + @echo "make (dir)/(test).valgrind.gen-suppressions -- generate suppressions" + @echo " and save to suppressions.log" + @echo "make inspect -- inspect all plugin features" + @echo + @echo + @echo "Additionally, you can use the GST_CHECKS environment variable to" + @echo "specify which test(s) should be run. This is useful if you are" + @echo "debugging a failure in one particular test, or want to reproduce" + @echo "a race condition in a single test." + @echo + @echo "Examples:" + @echo + @echo " GST_CHECKS=test_this,test_that make element/foobar.check" + @echo " GST_CHECKS=test_many_threads make element/foobar.forever" + @echo + +clean-local: clean-local-check + +$(CHECK_REGISTRY): + $(TESTS_ENVIRONMENT) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/check/gst/addresspool.c b/tests/check/gst/addresspool.c new file mode 100644 index 0000000..9a0ff54 --- /dev/null +++ b/tests/check/gst/addresspool.c @@ -0,0 +1,286 @@ +/* GStreamer + * Copyright (C) 2012 Wim Taymans + * + * 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. + */ + +#include + +#include + +GST_START_TEST (test_pool) +{ + GstRTSPAddressPool *pool; + GstRTSPAddress *addr, *addr2, *addr3; + GstRTSPAddressPoolResult res; + + pool = gst_rtsp_address_pool_new (); + + fail_if (gst_rtsp_address_pool_add_range (pool, + "233.252.0.1", "233.252.0.0", 5000, 5010, 1)); + fail_if (gst_rtsp_address_pool_add_range (pool, + "233.252.0.1", "::1", 5000, 5010, 1)); + fail_if (gst_rtsp_address_pool_add_range (pool, + "233.252.0.1", "ff02::1", 5000, 5010, 1)); + fail_if (gst_rtsp_address_pool_add_range (pool, + "233.252.0.1.1", "233.252.0.1", 5000, 5010, 1)); + fail_if (gst_rtsp_address_pool_add_range (pool, + "233.252.0.1", "233.252.0.1.1", 5000, 5010, 1)); + ASSERT_CRITICAL (gst_rtsp_address_pool_add_range (pool, + "233.252.0.0", "233.252.0.1", 5010, 5000, 1)); + + fail_unless (gst_rtsp_address_pool_add_range (pool, + "233.252.0.0", "233.252.0.255", 5000, 5010, 1)); + fail_unless (gst_rtsp_address_pool_add_range (pool, + "233.255.0.0", "233.255.0.0", 5000, 5010, 1)); + fail_unless (gst_rtsp_address_pool_add_range (pool, + "233.255.0.0", "233.255.0.0", 5020, 5020, 1)); + + /* should fail, we can't allocate a block of 256 ports */ + addr = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_MULTICAST, 256); + fail_unless (addr == NULL); + + addr = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_MULTICAST, 2); + fail_unless (addr != NULL); + + addr2 = gst_rtsp_address_copy (addr); + + gst_rtsp_address_free (addr2); + gst_rtsp_address_free (addr); + + addr = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_MULTICAST, 4); + fail_unless (addr != NULL); + + /* Will fail because pool is NULL */ + ASSERT_CRITICAL (gst_rtsp_address_pool_clear (NULL)); + + /* will fail because an address is allocated */ + ASSERT_CRITICAL (gst_rtsp_address_pool_clear (pool)); + + gst_rtsp_address_free (addr); + + gst_rtsp_address_pool_clear (pool); + + /* start with odd port to make sure we are allocated address + * starting with even port + */ + fail_unless (gst_rtsp_address_pool_add_range (pool, + "FF11:DB8::1", "FF11:DB8::1", 5001, 5003, 1)); + + addr = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_IPV6 | GST_RTSP_ADDRESS_FLAG_EVEN_PORT | + GST_RTSP_ADDRESS_FLAG_MULTICAST, 2); + fail_unless (addr != NULL); + fail_unless (addr->port == 5002); + fail_unless (!g_ascii_strcasecmp (addr->address, "FF11:DB8::1")); + + /* Will fail becuse there is only one IPv6 address left */ + addr2 = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_IPV6 | GST_RTSP_ADDRESS_FLAG_MULTICAST, 2); + fail_unless (addr2 == NULL); + + /* Will fail because the only IPv6 address left has an odd port */ + addr2 = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_IPV6 | GST_RTSP_ADDRESS_FLAG_EVEN_PORT | + GST_RTSP_ADDRESS_FLAG_MULTICAST, 1); + fail_unless (addr2 == NULL); + + addr2 = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_IPV4 | GST_RTSP_ADDRESS_FLAG_MULTICAST, 1); + fail_unless (addr2 == NULL); + + gst_rtsp_address_free (addr); + + gst_rtsp_address_pool_clear (pool); + + fail_unless (gst_rtsp_address_pool_add_range (pool, + "233.252.0.0", "233.252.0.255", 5000, 5002, 1)); + + addr = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_EVEN_PORT | GST_RTSP_ADDRESS_FLAG_MULTICAST, 2); + fail_unless (addr != NULL); + fail_unless (addr->port == 5000); + fail_unless (!strcmp (addr->address, "233.252.0.0")); + + addr2 = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_EVEN_PORT | GST_RTSP_ADDRESS_FLAG_MULTICAST, 2); + fail_unless (addr2 != NULL); + fail_unless (addr2->port == 5000); + fail_unless (!strcmp (addr2->address, "233.252.0.1")); + + gst_rtsp_address_free (addr); + gst_rtsp_address_free (addr2); + + addr = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_IPV6 | GST_RTSP_ADDRESS_FLAG_MULTICAST, 1); + fail_unless (addr == NULL); + + gst_rtsp_address_pool_clear (pool); + + fail_unless (gst_rtsp_address_pool_add_range (pool, + "233.252.1.1", "233.252.1.1", 5000, 5001, 1)); + + res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 3, + 1, &addr); + fail_unless (res == GST_RTSP_ADDRESS_POOL_ERANGE); + fail_unless (addr == NULL); + + res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.2", 5000, 2, + 1, &addr); + fail_unless (res == GST_RTSP_ADDRESS_POOL_ERANGE); + fail_unless (addr == NULL); + + res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 500, 2, 1, + &addr); + fail_unless (res == GST_RTSP_ADDRESS_POOL_ERANGE); + fail_unless (addr == NULL); + + res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 2, + 2, &addr); + fail_unless (res == GST_RTSP_ADDRESS_POOL_ERANGE); + fail_unless (addr == NULL); + + res = gst_rtsp_address_pool_reserve_address (pool, "2000::1", 5000, 2, 2, + &addr); + fail_unless (res == GST_RTSP_ADDRESS_POOL_EINVAL); + fail_unless (addr == NULL); + + res = gst_rtsp_address_pool_reserve_address (pool, "ff02::1", 5000, 2, 2, + &addr); + fail_unless (res == GST_RTSP_ADDRESS_POOL_ERANGE); + fail_unless (addr == NULL); + + res = gst_rtsp_address_pool_reserve_address (pool, "1.1", 5000, 2, 2, &addr); + fail_unless (res == GST_RTSP_ADDRESS_POOL_EINVAL); + fail_unless (addr == NULL); + + res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 2, + 1, &addr); + fail_unless (res == GST_RTSP_ADDRESS_POOL_OK); + fail_unless (addr != NULL); + fail_unless (addr->port == 5000); + fail_unless (!strcmp (addr->address, "233.252.1.1")); + + res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 2, + 1, &addr2); + fail_unless (res == GST_RTSP_ADDRESS_POOL_ERESERVED); + fail_unless (addr2 == NULL); + + gst_rtsp_address_free (addr); + gst_rtsp_address_pool_clear (pool); + + fail_unless (gst_rtsp_address_pool_add_range (pool, + "233.252.1.1", "233.252.1.3", 5000, 5001, 1)); + + res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 2, + 1, &addr); + fail_unless (addr != NULL); + fail_unless (addr->port == 5000); + fail_unless (!strcmp (addr->address, "233.252.1.1")); + + res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.3", 5000, 2, + 1, &addr2); + fail_unless (addr2 != NULL); + fail_unless (addr2->port == 5000); + fail_unless (!strcmp (addr2->address, "233.252.1.3")); + + addr3 = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_EVEN_PORT | GST_RTSP_ADDRESS_FLAG_MULTICAST, 2); + fail_unless (addr3 != NULL); + fail_unless (addr3->port == 5000); + fail_unless (!strcmp (addr3->address, "233.252.1.2")); + + fail_unless (gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_EVEN_PORT | GST_RTSP_ADDRESS_FLAG_MULTICAST, 2) + == NULL); + + gst_rtsp_address_free (addr); + gst_rtsp_address_free (addr2); + gst_rtsp_address_free (addr3); + gst_rtsp_address_pool_clear (pool); + + fail_unless (gst_rtsp_address_pool_add_range (pool, + "233.252.1.1", "233.252.1.1", 5000, 5001, 1)); + fail_if (gst_rtsp_address_pool_has_unicast_addresses (pool)); + fail_unless (gst_rtsp_address_pool_add_range (pool, + "192.168.1.1", "192.168.1.1", 6000, 6001, 0)); + fail_unless (gst_rtsp_address_pool_has_unicast_addresses (pool)); + + addr = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_EVEN_PORT | GST_RTSP_ADDRESS_FLAG_MULTICAST, 2); + fail_unless (addr != NULL); + fail_unless (addr->port == 5000); + fail_unless (!strcmp (addr->address, "233.252.1.1")); + gst_rtsp_address_free (addr); + + addr = gst_rtsp_address_pool_acquire_address (pool, + GST_RTSP_ADDRESS_FLAG_EVEN_PORT | GST_RTSP_ADDRESS_FLAG_UNICAST, 2); + fail_unless (addr != NULL); + fail_unless (addr->port == 6000); + fail_unless (!strcmp (addr->address, "192.168.1.1")); + gst_rtsp_address_free (addr); + + fail_unless (gst_rtsp_address_pool_add_range (pool, + GST_RTSP_ADDRESS_POOL_ANY_IPV4, GST_RTSP_ADDRESS_POOL_ANY_IPV4, 5000, + 5001, 0)); + res = + gst_rtsp_address_pool_reserve_address (pool, "192.168.0.1", 5000, 1, 0, + &addr); + fail_unless (res == GST_RTSP_ADDRESS_POOL_ERANGE); + res = + gst_rtsp_address_pool_reserve_address (pool, "0.0.0.0", 5000, 1, 0, + &addr); + fail_unless (res == GST_RTSP_ADDRESS_POOL_OK); + gst_rtsp_address_free (addr); + gst_rtsp_address_pool_clear (pool); + + /* Error case 2. Using ANY as min address makes it possible to allocate the + * same address twice */ + fail_unless (gst_rtsp_address_pool_add_range (pool, + GST_RTSP_ADDRESS_POOL_ANY_IPV4, "255.255.255.255", 5000, 5001, 0)); + res = + gst_rtsp_address_pool_reserve_address (pool, "192.168.0.1", 5000, 1, 0, + &addr); + fail_unless (res == GST_RTSP_ADDRESS_POOL_OK); + res = + gst_rtsp_address_pool_reserve_address (pool, "192.168.0.1", 5000, 1, 0, + &addr2); + fail_unless (res == GST_RTSP_ADDRESS_POOL_ERESERVED); + gst_rtsp_address_free (addr); + gst_rtsp_address_pool_clear (pool); + + g_object_unref (pool); +} + +GST_END_TEST; + +static Suite * +rtspaddresspool_suite (void) +{ + Suite *s = suite_create ("rtspaddresspool"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_set_timeout (tc, 20); + tcase_add_test (tc, test_pool); + + return s; +} + +GST_CHECK_MAIN (rtspaddresspool); diff --git a/tests/check/gst/client.c b/tests/check/gst/client.c new file mode 100644 index 0000000..1bbd67d --- /dev/null +++ b/tests/check/gst/client.c @@ -0,0 +1,929 @@ +/* GStreamer + * Copyright (C) 2012 Wim Taymans + * + * 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. + */ + +#include + +#include + +static gchar * session_id; +static gint cseq; +static guint expected_session_timeout = 60; + +static gboolean +test_response_200 (GstRTSPClient * client, GstRTSPMessage * response, + gboolean close, gpointer user_data) +{ + GstRTSPStatusCode code; + const gchar *reason; + GstRTSPVersion version; + + fail_unless (gst_rtsp_message_get_type (response) == + GST_RTSP_MESSAGE_RESPONSE); + + fail_unless (gst_rtsp_message_parse_response (response, &code, &reason, + &version) + == GST_RTSP_OK); + fail_unless (code == GST_RTSP_STS_OK); + fail_unless (g_str_equal (reason, "OK")); + fail_unless (version == GST_RTSP_VERSION_1_0); + + return TRUE; +} + +static gboolean +test_response_400 (GstRTSPClient * client, GstRTSPMessage * response, + gboolean close, gpointer user_data) +{ + GstRTSPStatusCode code; + const gchar *reason; + GstRTSPVersion version; + + fail_unless (gst_rtsp_message_get_type (response) == + GST_RTSP_MESSAGE_RESPONSE); + + fail_unless (gst_rtsp_message_parse_response (response, &code, &reason, + &version) + == GST_RTSP_OK); + fail_unless (code == GST_RTSP_STS_BAD_REQUEST); + fail_unless (g_str_equal (reason, "Bad Request")); + fail_unless (version == GST_RTSP_VERSION_1_0); + + return TRUE; +} + +static gboolean +test_response_404 (GstRTSPClient * client, GstRTSPMessage * response, + gboolean close, gpointer user_data) +{ + GstRTSPStatusCode code; + const gchar *reason; + GstRTSPVersion version; + + fail_unless (gst_rtsp_message_get_type (response) == + GST_RTSP_MESSAGE_RESPONSE); + + fail_unless (gst_rtsp_message_parse_response (response, &code, &reason, + &version) + == GST_RTSP_OK); + fail_unless (code == GST_RTSP_STS_NOT_FOUND); + fail_unless (g_str_equal (reason, "Not Found")); + fail_unless (version == GST_RTSP_VERSION_1_0); + + return TRUE; +} + +static gboolean +test_response_454 (GstRTSPClient * client, GstRTSPMessage * response, + gboolean close, gpointer user_data) +{ + GstRTSPStatusCode code; + const gchar *reason; + GstRTSPVersion version; + + fail_unless (gst_rtsp_message_get_type (response) == + GST_RTSP_MESSAGE_RESPONSE); + + fail_unless (gst_rtsp_message_parse_response (response, &code, &reason, + &version) + == GST_RTSP_OK); + fail_unless (code == GST_RTSP_STS_SESSION_NOT_FOUND); + fail_unless (g_str_equal (reason, "Session Not Found")); + fail_unless (version == GST_RTSP_VERSION_1_0); + + return TRUE; +} + +static GstRTSPClient * +setup_client (const gchar * launch_line) +{ + GstRTSPClient *client; + GstRTSPSessionPool *session_pool; + GstRTSPMountPoints *mount_points; + GstRTSPMediaFactory *factory; + GstRTSPThreadPool *thread_pool; + + client = gst_rtsp_client_new (); + + session_pool = gst_rtsp_session_pool_new (); + gst_rtsp_client_set_session_pool (client, session_pool); + + mount_points = gst_rtsp_mount_points_new (); + factory = gst_rtsp_media_factory_new (); + if (launch_line == NULL) + gst_rtsp_media_factory_set_launch (factory, + "videotestsrc ! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96"); + else + gst_rtsp_media_factory_set_launch (factory, launch_line); + + gst_rtsp_mount_points_add_factory (mount_points, "/test", factory); + gst_rtsp_client_set_mount_points (client, mount_points); + + thread_pool = gst_rtsp_thread_pool_new (); + gst_rtsp_client_set_thread_pool (client, thread_pool); + + g_object_unref (mount_points); + g_object_unref (session_pool); + g_object_unref (thread_pool); + + return client; +} + +static void +teardown_client (GstRTSPClient * client) +{ + gst_rtsp_client_set_thread_pool (client, NULL); + g_object_unref (client); +} + +GST_START_TEST (test_request) +{ + GstRTSPClient *client; + GstRTSPMessage request = { 0, }; + gchar *str; + GstRTSPConnection *conn; + GSocket *sock; + GError *error = NULL; + + client = gst_rtsp_client_new (); + + /* OPTIONS with invalid url */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS, + "foopy://padoop/") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); + g_free (str); + + gst_rtsp_client_set_send_func (client, test_response_400, NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + + gst_rtsp_message_unset (&request); + + /* OPTIONS with unknown session id */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS, + "rtsp://localhost/test") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); + g_free (str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, "foobar"); + + gst_rtsp_client_set_send_func (client, test_response_454, NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + + gst_rtsp_message_unset (&request); + + /* OPTIONS with an absolute path instead of an absolute url */ + /* set host information */ + sock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_TCP, &error); + g_assert_no_error (error); + gst_rtsp_connection_create_from_socket (sock, "localhost", 444, NULL, &conn); + fail_unless (gst_rtsp_client_set_connection (client, conn)); + g_object_unref (sock); + + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS, + "/test") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); + g_free (str); + + gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + /* OPTIONS with an absolute path instead of an absolute url with invalid + * host information */ + g_object_unref (client); + client = gst_rtsp_client_new (); + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS, + "/test") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); + g_free (str); + + gst_rtsp_client_set_send_func (client, test_response_400, NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + g_object_unref (client); +} + +GST_END_TEST; + +static gboolean +test_option_response_200 (GstRTSPClient * client, GstRTSPMessage * response, + gboolean close, gpointer user_data) +{ + GstRTSPStatusCode code; + const gchar *reason; + GstRTSPVersion version; + gchar *str; + GstRTSPMethod methods; + + fail_unless (gst_rtsp_message_get_type (response) == + GST_RTSP_MESSAGE_RESPONSE); + + fail_unless (gst_rtsp_message_parse_response (response, &code, &reason, + &version) + == GST_RTSP_OK); + fail_unless (code == GST_RTSP_STS_OK); + fail_unless (g_str_equal (reason, "OK")); + fail_unless (version == GST_RTSP_VERSION_1_0); + + fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str, + 0) == GST_RTSP_OK); + fail_unless (atoi (str) == cseq++); + + fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_PUBLIC, &str, + 0) == GST_RTSP_OK); + + methods = gst_rtsp_options_from_text (str); + fail_if (methods == 0); + fail_unless (methods == (GST_RTSP_DESCRIBE | + GST_RTSP_OPTIONS | + GST_RTSP_PAUSE | + GST_RTSP_PLAY | + GST_RTSP_SETUP | + GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN)); + + return TRUE; +} + +GST_START_TEST (test_options) +{ + GstRTSPClient *client; + GstRTSPMessage request = { 0, }; + gchar *str; + + client = gst_rtsp_client_new (); + + /* simple OPTIONS */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS, + "rtsp://localhost/test") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); + g_free (str); + + gst_rtsp_client_set_send_func (client, test_option_response_200, NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + g_object_unref (client); +} + +GST_END_TEST; + +GST_START_TEST (test_describe) +{ + GstRTSPClient *client; + GstRTSPMessage request = { 0, }; + gchar *str; + + client = gst_rtsp_client_new (); + + /* simple DESCRIBE for non-existing url */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE, + "rtsp://localhost/test") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); + g_free (str); + + gst_rtsp_client_set_send_func (client, test_response_404, NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + g_object_unref (client); + + /* simple DESCRIBE for an existing url */ + client = setup_client (NULL); + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE, + "rtsp://localhost/test") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); + g_free (str); + + gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + teardown_client (client); +} + +GST_END_TEST; + +static const gchar *expected_transport = NULL;; + +static gboolean +test_setup_response_200_multicast (GstRTSPClient * client, + GstRTSPMessage * response, gboolean close, gpointer user_data) +{ + GstRTSPStatusCode code; + const gchar *reason; + GstRTSPVersion version; + gchar *str; + GstRTSPSessionPool *session_pool; + GstRTSPSession *session; + gchar **session_hdr_params; + + fail_unless (expected_transport != NULL); + + fail_unless (gst_rtsp_message_get_type (response) == + GST_RTSP_MESSAGE_RESPONSE); + + fail_unless (gst_rtsp_message_parse_response (response, &code, &reason, + &version) + == GST_RTSP_OK); + fail_unless (code == GST_RTSP_STS_OK); + fail_unless (g_str_equal (reason, "OK")); + fail_unless (version == GST_RTSP_VERSION_1_0); + + fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str, + 0) == GST_RTSP_OK); + fail_unless (atoi (str) == cseq++); + + fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_TRANSPORT, + &str, 0) == GST_RTSP_OK); + + fail_unless (!strcmp (str, expected_transport)); + + fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_SESSION, + &str, 0) == GST_RTSP_OK); + session_hdr_params = g_strsplit (str, ";", -1); + + /* session-id value */ + fail_unless (session_hdr_params[0] != NULL); + + if (expected_session_timeout != 60) { + /* session timeout param */ + gchar *timeout_str = g_strdup_printf ("timeout=%u", + expected_session_timeout); + + fail_unless (session_hdr_params[1] != NULL); + g_strstrip (session_hdr_params[1]); + fail_unless (g_strcmp0 (session_hdr_params[1], timeout_str) == 0); + g_free (timeout_str); + } + + session_pool = gst_rtsp_client_get_session_pool (client); + fail_unless (session_pool != NULL); + + fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 1); + session = gst_rtsp_session_pool_find (session_pool, session_hdr_params[0]); + g_strfreev (session_hdr_params); + + /* remember session id to be able to send teardown */ + session_id = g_strdup (gst_rtsp_session_get_sessionid (session)); + fail_unless (session_id != NULL); + + fail_unless (session != NULL); + g_object_unref (session); + + g_object_unref (session_pool); + + + return TRUE; +} + +static gboolean +test_teardown_response_200 (GstRTSPClient * client, + GstRTSPMessage * response, gboolean close, gpointer user_data) +{ + GstRTSPStatusCode code; + const gchar *reason; + GstRTSPVersion version; + + fail_unless (gst_rtsp_message_get_type (response) == + GST_RTSP_MESSAGE_RESPONSE); + + fail_unless (gst_rtsp_message_parse_response (response, &code, &reason, + &version) + == GST_RTSP_OK); + fail_unless (code == GST_RTSP_STS_OK); + fail_unless (g_str_equal (reason, "OK")); + fail_unless (version == GST_RTSP_VERSION_1_0); + + return TRUE; +} + +static void +send_teardown (GstRTSPClient * client) +{ + GstRTSPMessage request = { 0, }; + gchar *str; + + fail_unless (session_id != NULL); + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_TEARDOWN, + "rtsp://localhost/test") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, + session_id); + gst_rtsp_client_set_send_func (client, test_teardown_response_200, + NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + g_free (session_id); + session_id = NULL; +} + +static GstRTSPClient * +setup_multicast_client (void) +{ + GstRTSPClient *client; + GstRTSPSessionPool *session_pool; + GstRTSPMountPoints *mount_points; + GstRTSPMediaFactory *factory; + GstRTSPAddressPool *address_pool; + GstRTSPThreadPool *thread_pool; + + client = gst_rtsp_client_new (); + + session_pool = gst_rtsp_session_pool_new (); + gst_rtsp_client_set_session_pool (client, session_pool); + + mount_points = gst_rtsp_mount_points_new (); + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, + "audiotestsrc ! audio/x-raw,rate=44100 ! audioconvert ! rtpL16pay name=pay0"); + address_pool = gst_rtsp_address_pool_new (); + fail_unless (gst_rtsp_address_pool_add_range (address_pool, + "233.252.0.1", "233.252.0.1", 5000, 5010, 1)); + gst_rtsp_media_factory_set_address_pool (factory, address_pool); + gst_rtsp_media_factory_add_role (factory, "user", + "media.factory.access", G_TYPE_BOOLEAN, TRUE, + "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL); + gst_rtsp_mount_points_add_factory (mount_points, "/test", factory); + gst_rtsp_client_set_mount_points (client, mount_points); + + thread_pool = gst_rtsp_thread_pool_new (); + gst_rtsp_client_set_thread_pool (client, thread_pool); + + g_object_unref (mount_points); + g_object_unref (session_pool); + g_object_unref (address_pool); + g_object_unref (thread_pool); + + return client; +} + +GST_START_TEST (test_client_multicast_transport_404) +{ + GstRTSPClient *client; + GstRTSPMessage request = { 0, }; + gchar *str; + + client = setup_multicast_client (); + + /* simple SETUP for non-existing url */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP, + "rtsp://localhost/test2/stream=0") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, + "RTP/AVP;multicast"); + + gst_rtsp_client_set_send_func (client, test_response_404, NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + teardown_client (client); +} + +GST_END_TEST; + +static void +new_session_cb (GObject * client, GstRTSPSession * session, gpointer user_data) +{ + GST_DEBUG ("%p: new session %p", client, session); + gst_rtsp_session_set_timeout (session, expected_session_timeout); +} + +GST_START_TEST (test_client_multicast_transport) +{ + GstRTSPClient *client; + GstRTSPMessage request = { 0, }; + gchar *str; + + client = setup_multicast_client (); + + expected_session_timeout = 20; + g_signal_connect (G_OBJECT (client), "new-session", + G_CALLBACK (new_session_cb), NULL); + + /* simple SETUP with a valid URI and multicast */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP, + "rtsp://localhost/test/stream=0") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, + "RTP/AVP;multicast"); + + expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;" + "ttl=1;port=5000-5001;mode=\"PLAY\""; + gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast, + NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + expected_transport = NULL; + expected_session_timeout = 60; + + send_teardown (client); + + teardown_client (client); +} + +GST_END_TEST; + +GST_START_TEST (test_client_multicast_ignore_transport_specific) +{ + GstRTSPClient *client; + GstRTSPMessage request = { 0, }; + gchar *str; + + client = setup_multicast_client (); + + /* simple SETUP with a valid URI and multicast and a specific dest, + * but ignore it */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP, + "rtsp://localhost/test/stream=0") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, + "RTP/AVP;multicast;destination=233.252.0.2;ttl=2;port=5001-5006;"); + + expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;" + "ttl=1;port=5000-5001;mode=\"PLAY\""; + gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast, + NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + expected_transport = NULL; + + send_teardown (client); + + teardown_client (client); +} + +GST_END_TEST; + +static gboolean +test_setup_response_461 (GstRTSPClient * client, + GstRTSPMessage * response, gboolean close, gpointer user_data) +{ + GstRTSPStatusCode code; + const gchar *reason; + GstRTSPVersion version; + gchar *str; + + fail_unless (expected_transport == NULL); + + fail_unless (gst_rtsp_message_get_type (response) == + GST_RTSP_MESSAGE_RESPONSE); + + fail_unless (gst_rtsp_message_parse_response (response, &code, &reason, + &version) + == GST_RTSP_OK); + fail_unless (code == GST_RTSP_STS_UNSUPPORTED_TRANSPORT); + fail_unless (g_str_equal (reason, "Unsupported transport")); + fail_unless (version == GST_RTSP_VERSION_1_0); + + fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str, + 0) == GST_RTSP_OK); + fail_unless (atoi (str) == cseq++); + + + return TRUE; +} + +GST_START_TEST (test_client_multicast_invalid_transport_specific) +{ + GstRTSPClient *client; + GstRTSPMessage request = { 0, }; + gchar *str; + GstRTSPSessionPool *session_pool; + GstRTSPContext ctx = { NULL }; + + client = setup_multicast_client (); + + ctx.client = client; + ctx.auth = gst_rtsp_auth_new (); + ctx.token = + gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS, + G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING, + "user", NULL); + gst_rtsp_context_push_current (&ctx); + + /* simple SETUP with a valid URI and multicast, but an invalid ip */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP, + "rtsp://localhost/test/stream=0") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, + "RTP/AVP;multicast;destination=233.252.0.2;ttl=1;port=5000-5001;"); + + gst_rtsp_client_set_send_func (client, test_setup_response_461, NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + session_pool = gst_rtsp_client_get_session_pool (client); + fail_unless (session_pool != NULL); + /* FIXME: There seems to be a leak of a session here ! */ + fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 0); + g_object_unref (session_pool); + + + + /* simple SETUP with a valid URI and multicast, but an invalid prt */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP, + "rtsp://localhost/test/stream=0") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, + "RTP/AVP;multicast;destination=233.252.0.1;ttl=1;port=6000-6001;"); + + gst_rtsp_client_set_send_func (client, test_setup_response_461, NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + session_pool = gst_rtsp_client_get_session_pool (client); + fail_unless (session_pool != NULL); + /* FIXME: There seems to be a leak of a session here ! */ + fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 0); + g_object_unref (session_pool); + + + + /* simple SETUP with a valid URI and multicast, but an invalid ttl */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP, + "rtsp://localhost/test/stream=0") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, + "RTP/AVP;multicast;destination=233.252.0.1;ttl=2;port=5000-5001;"); + + gst_rtsp_client_set_send_func (client, test_setup_response_461, NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + session_pool = gst_rtsp_client_get_session_pool (client); + fail_unless (session_pool != NULL); + /* FIXME: There seems to be a leak of a session here ! */ + fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 0); + g_object_unref (session_pool); + + + teardown_client (client); + g_object_unref (ctx.auth); + gst_rtsp_token_unref (ctx.token); + gst_rtsp_context_pop_current (&ctx); +} + +GST_END_TEST; + +GST_START_TEST (test_client_multicast_transport_specific) +{ + GstRTSPClient *client; + GstRTSPMessage request = { 0, }; + gchar *str; + GstRTSPSessionPool *session_pool; + GstRTSPContext ctx = { NULL }; + + client = setup_multicast_client (); + + ctx.client = client; + ctx.auth = gst_rtsp_auth_new (); + ctx.token = + gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS, + G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING, + "user", NULL); + gst_rtsp_context_push_current (&ctx); + + expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;" + "ttl=1;port=5000-5001;mode=\"PLAY\""; + + /* simple SETUP with a valid URI and multicast, but an invalid ip */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP, + "rtsp://localhost/test/stream=0") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, + expected_transport); + + gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast, + NULL, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + expected_transport = NULL; + + gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast, + NULL, NULL); + session_pool = gst_rtsp_client_get_session_pool (client); + fail_unless (session_pool != NULL); + fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 1); + g_object_unref (session_pool); + + send_teardown (client); + + teardown_client (client); + g_object_unref (ctx.auth); + gst_rtsp_token_unref (ctx.token); + gst_rtsp_context_pop_current (&ctx); +} + +GST_END_TEST; + +static gboolean +test_response_sdp (GstRTSPClient * client, GstRTSPMessage * response, + gboolean close, gpointer user_data) +{ + guint8 *data; + guint size; + GstSDPMessage *sdp_msg; + const GstSDPMedia *sdp_media; + const GstSDPBandwidth *bw; + gint bandwidth_val = GPOINTER_TO_INT (user_data); + + fail_unless (gst_rtsp_message_get_body (response, &data, &size) + == GST_RTSP_OK); + gst_sdp_message_new (&sdp_msg); + fail_unless (gst_sdp_message_parse_buffer (data, size, sdp_msg) + == GST_SDP_OK); + + /* session description */ + /* v= */ + fail_unless (gst_sdp_message_get_version (sdp_msg) != NULL); + /* o= */ + fail_unless (gst_sdp_message_get_origin (sdp_msg) != NULL); + /* s= */ + fail_unless (gst_sdp_message_get_session_name (sdp_msg) != NULL); + /* t=0 0 */ + fail_unless (gst_sdp_message_times_len (sdp_msg) == 0); + + /* verify number of medias */ + fail_unless (gst_sdp_message_medias_len (sdp_msg) == 1); + + /* media description */ + sdp_media = gst_sdp_message_get_media (sdp_msg, 0); + fail_unless (sdp_media != NULL); + + /* m= */ + fail_unless (gst_sdp_media_get_media (sdp_media) != NULL); + + /* media bandwidth */ + if (bandwidth_val) { + fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 1); + bw = gst_sdp_media_get_bandwidth (sdp_media, 0); + fail_unless (bw != NULL); + fail_unless (g_strcmp0 (bw->bwtype, "AS") == 0); + fail_unless (bw->bandwidth == bandwidth_val); + } else { + fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 0); + } + + gst_sdp_message_free (sdp_msg); + + return TRUE; +} + +static void +test_client_sdp (const gchar * launch_line, guint * bandwidth_val) +{ + GstRTSPClient *client; + GstRTSPMessage request = { 0, }; + gchar *str; + + /* simple DESCRIBE for an existing url */ + client = setup_client (launch_line); + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE, + "rtsp://localhost/test") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); + g_free (str); + + gst_rtsp_client_set_send_func (client, test_response_sdp, + (gpointer) bandwidth_val, NULL); + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + teardown_client (client); +} + +GST_START_TEST (test_client_sdp_with_max_bitrate_tag) +{ + test_client_sdp ("videotestsrc " + "! taginject tags=\"maximum-bitrate=(uint)50000000\" " + "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", + GUINT_TO_POINTER (50000)); + + + /* max-bitrate=0: no bandwidth line */ + test_client_sdp ("videotestsrc " + "! taginject tags=\"maximum-bitrate=(uint)0\" " + "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", + GUINT_TO_POINTER (0)); +} + +GST_END_TEST; + +GST_START_TEST (test_client_sdp_with_bitrate_tag) +{ + test_client_sdp ("videotestsrc " + "! taginject tags=\"bitrate=(uint)7000000\" " + "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", + GUINT_TO_POINTER (7000)); + + /* bitrate=0: no bandwdith line */ + test_client_sdp ("videotestsrc " + "! taginject tags=\"bitrate=(uint)0\" " + "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", + GUINT_TO_POINTER (0)); +} + +GST_END_TEST; + +GST_START_TEST (test_client_sdp_with_max_bitrate_and_bitrate_tags) +{ + test_client_sdp ("videotestsrc " + "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)50000000\" " + "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", + GUINT_TO_POINTER (50000)); + + /* max-bitrate is zero: fallback to bitrate */ + test_client_sdp ("videotestsrc " + "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)0\" " + "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", + GUINT_TO_POINTER (7000)); + + /* max-bitrate=bitrate=0o: no bandwidth line */ + test_client_sdp ("videotestsrc " + "! taginject tags=\"bitrate=(uint)0,maximum-bitrate=(uint)0\" " + "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", + GUINT_TO_POINTER (0)); +} + +GST_END_TEST; + +GST_START_TEST (test_client_sdp_with_no_bitrate_tags) +{ + test_client_sdp ("videotestsrc " + "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", NULL); +} + +GST_END_TEST; + +static Suite * +rtspclient_suite (void) +{ + Suite *s = suite_create ("rtspclient"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_set_timeout (tc, 20); + tcase_add_test (tc, test_request); + tcase_add_test (tc, test_options); + tcase_add_test (tc, test_describe); + tcase_add_test (tc, test_client_multicast_transport_404); + tcase_add_test (tc, test_client_multicast_transport); + tcase_add_test (tc, test_client_multicast_ignore_transport_specific); + tcase_add_test (tc, test_client_multicast_invalid_transport_specific); + tcase_add_test (tc, test_client_multicast_transport_specific); + tcase_add_test (tc, test_client_sdp_with_max_bitrate_tag); + tcase_add_test (tc, test_client_sdp_with_bitrate_tag); + tcase_add_test (tc, test_client_sdp_with_max_bitrate_and_bitrate_tags); + tcase_add_test (tc, test_client_sdp_with_no_bitrate_tags); + + return s; +} + +GST_CHECK_MAIN (rtspclient); diff --git a/tests/check/gst/media.c b/tests/check/gst/media.c new file mode 100644 index 0000000..c7d680e --- /dev/null +++ b/tests/check/gst/media.c @@ -0,0 +1,434 @@ +/* GStreamer + * Copyright (C) 2012 Wim Taymans + * + * 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. + */ + +#include + +#include + +GST_START_TEST (test_launch) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url; + GstRTSPStream *stream; + GstRTSPTimeRange *range; + gchar *str; + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + fail_unless (gst_rtsp_media_n_streams (media) == 1); + + stream = gst_rtsp_media_get_stream (media, 0); + fail_unless (stream != NULL); + + /* fails, need to be prepared */ + str = gst_rtsp_media_get_range_string (media, FALSE, GST_RTSP_RANGE_NPT); + fail_unless (str == NULL); + + fail_unless (gst_rtsp_range_parse ("npt=5.0-", &range) == GST_RTSP_OK); + /* fails, need to be prepared */ + fail_if (gst_rtsp_media_seek (media, range)); + + pool = gst_rtsp_thread_pool_new (); + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + + fail_unless (gst_rtsp_media_prepare (media, thread)); + + str = gst_rtsp_media_get_range_string (media, FALSE, GST_RTSP_RANGE_NPT); + fail_unless (g_str_equal (str, "npt=0-")); + g_free (str); + + str = gst_rtsp_media_get_range_string (media, TRUE, GST_RTSP_RANGE_NPT); + fail_unless (g_str_equal (str, "npt=0-")); + g_free (str); + + fail_unless (gst_rtsp_media_seek (media, range)); + + str = gst_rtsp_media_get_range_string (media, FALSE, GST_RTSP_RANGE_NPT); + fail_unless (g_str_equal (str, "npt=5-")); + g_free (str); + + str = gst_rtsp_media_get_range_string (media, TRUE, GST_RTSP_RANGE_NPT); + fail_unless (g_str_equal (str, "npt=5-")); + g_free (str); + + fail_unless (gst_rtsp_media_unprepare (media)); + + /* should fail again */ + str = gst_rtsp_media_get_range_string (media, FALSE, GST_RTSP_RANGE_NPT); + fail_unless (str == NULL); + fail_if (gst_rtsp_media_seek (media, range)); + + gst_rtsp_range_free (range); + g_object_unref (media); + + gst_rtsp_url_free (url); + g_object_unref (factory); + + g_object_unref (pool); + + gst_rtsp_thread_pool_cleanup (); +} + +GST_END_TEST; + +GST_START_TEST (test_media) +{ + GstRTSPMedia *media; + GstElement *bin, *e1, *e2; + + bin = gst_bin_new ("bin"); + fail_if (bin == NULL); + + e1 = gst_element_factory_make ("videotestsrc", NULL); + fail_if (e1 == NULL); + + e2 = gst_element_factory_make ("rtpvrawpay", "pay0"); + fail_if (e2 == NULL); + g_object_set (e2, "pt", 96, NULL); + + gst_bin_add_many (GST_BIN_CAST (bin), e1, e2, NULL); + gst_element_link_many (e1, e2, NULL); + + media = gst_rtsp_media_new (bin); + fail_unless (GST_IS_RTSP_MEDIA (media)); + g_object_unref (media); +} + +GST_END_TEST; + +static void +test_prepare_reusable (GstRTSPThreadPool * pool, const gchar * launch_line) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url; + GstRTSPThread *thread; + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, launch_line); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + fail_unless (gst_rtsp_media_n_streams (media) == 1); + + g_object_set (G_OBJECT (media), "reusable", TRUE, NULL); + + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + fail_unless (gst_rtsp_media_prepare (media, thread)); + fail_unless (gst_rtsp_media_unprepare (media)); + fail_unless (gst_rtsp_media_n_streams (media) == 1); + + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + fail_unless (gst_rtsp_media_prepare (media, thread)); + fail_unless (gst_rtsp_media_unprepare (media)); + + g_object_unref (media); + gst_rtsp_url_free (url); + g_object_unref (factory); +} + +GST_START_TEST (test_media_prepare) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url; + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + + pool = gst_rtsp_thread_pool_new (); + + /* test non-reusable media first */ + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + fail_unless (gst_rtsp_media_n_streams (media) == 1); + + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + fail_unless (gst_rtsp_media_prepare (media, thread)); + fail_unless (gst_rtsp_media_unprepare (media)); + fail_unless (gst_rtsp_media_n_streams (media) == 1); + + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + fail_if (gst_rtsp_media_prepare (media, thread)); + + g_object_unref (media); + gst_rtsp_url_free (url); + g_object_unref (factory); + + /* test reusable media */ + test_prepare_reusable (pool, "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + test_prepare_reusable (pool, + "( videotestsrc is-live=true ! rtpvrawpay pt=96 name=pay0 )"); + + g_object_unref (pool); + gst_rtsp_thread_pool_cleanup (); +} + +GST_END_TEST; + +static void +on_notify_caps (GstPad * pad, GParamSpec * pspec, GstElement * pay) +{ + GstCaps *caps; + static gboolean have_caps = FALSE; + + g_object_get (pad, "caps", &caps, NULL); + + GST_DEBUG ("notify %" GST_PTR_FORMAT, caps); + + if (caps) { + if (!have_caps) { + g_signal_emit_by_name (pay, "pad-added", pad); + g_signal_emit_by_name (pay, "no-more-pads", NULL); + have_caps = TRUE; + } + gst_caps_unref (caps); + } else { + if (have_caps) { + g_signal_emit_by_name (pay, "pad-removed", pad); + have_caps = FALSE; + } + } +} + +GST_START_TEST (test_media_dyn_prepare) +{ + GstRTSPMedia *media; + GstElement *bin, *src, *pay; + GstElement *pipeline; + GstPad *srcpad; + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + + bin = gst_bin_new ("bin"); + fail_if (bin == NULL); + + src = gst_element_factory_make ("videotestsrc", NULL); + fail_if (src == NULL); + + pay = gst_element_factory_make ("rtpvrawpay", "dynpay0"); + fail_if (pay == NULL); + g_object_set (pay, "pt", 96, NULL); + + gst_bin_add_many (GST_BIN_CAST (bin), src, pay, NULL); + gst_element_link_many (src, pay, NULL); + + media = gst_rtsp_media_new (bin); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + g_object_set (G_OBJECT (media), "reusable", TRUE, NULL); + + pipeline = gst_pipeline_new ("media-pipeline"); + gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline)); + + gst_rtsp_media_collect_streams (media); + + srcpad = gst_element_get_static_pad (pay, "src"); + + g_signal_connect (srcpad, "notify::caps", (GCallback) on_notify_caps, pay); + + pool = gst_rtsp_thread_pool_new (); + + fail_unless (gst_rtsp_media_n_streams (media) == 0); + + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + fail_unless (gst_rtsp_media_prepare (media, thread)); + fail_unless (gst_rtsp_media_n_streams (media) == 1); + fail_unless (gst_rtsp_media_unprepare (media)); + fail_unless (gst_rtsp_media_n_streams (media) == 0); + + fail_unless (gst_rtsp_media_n_streams (media) == 0); + + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + fail_unless (gst_rtsp_media_prepare (media, thread)); + fail_unless (gst_rtsp_media_n_streams (media) == 1); + fail_unless (gst_rtsp_media_unprepare (media)); + fail_unless (gst_rtsp_media_n_streams (media) == 0); + + gst_object_unref (srcpad); + g_object_unref (media); + g_object_unref (pool); + + gst_rtsp_thread_pool_cleanup (); +} + +GST_END_TEST; + +GST_START_TEST (test_media_prepare_port_alloc_fail) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url; + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + GstRTSPAddressPool *addrpool; + + pool = gst_rtsp_thread_pool_new (); + + factory = gst_rtsp_media_factory_new (); + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( fakesrc is-live=true ! text/plain ! rtpgstpay name=pay0 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + addrpool = gst_rtsp_address_pool_new (); + fail_unless (gst_rtsp_address_pool_add_range (addrpool, "192.168.1.1", + "192.168.1.1", 6000, 6001, 0)); + gst_rtsp_media_set_address_pool (media, addrpool); + + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + fail_if (gst_rtsp_media_prepare (media, thread)); + + g_object_unref (media); + g_object_unref (addrpool); + gst_rtsp_url_free (url); + g_object_unref (factory); + g_object_unref (pool); +} + +GST_END_TEST; + +GST_START_TEST (test_media_take_pipeline) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url; + GstElement *pipeline; + + factory = gst_rtsp_media_factory_new (); + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + gst_rtsp_media_factory_set_launch (factory, + "( fakesrc ! text/plain ! rtpgstpay name=pay0 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + pipeline = gst_pipeline_new ("media-pipeline"); + gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline)); + + g_object_unref (media); + gst_rtsp_url_free (url); + g_object_unref (factory); +} + +GST_END_TEST; + +GST_START_TEST (test_media_reset) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url; + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + + pool = gst_rtsp_thread_pool_new (); + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + gst_rtsp_url_parse ("rtsp://localhost:8554/test", &url); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + fail_unless (gst_rtsp_media_prepare (media, thread)); + fail_unless (gst_rtsp_media_suspend (media)); + fail_unless (gst_rtsp_media_unprepare (media)); + g_object_unref (media); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + gst_rtsp_media_set_suspend_mode (media, GST_RTSP_SUSPEND_MODE_RESET); + fail_unless (gst_rtsp_media_prepare (media, thread)); + fail_unless (gst_rtsp_media_suspend (media)); + fail_unless (gst_rtsp_media_unprepare (media)); + g_object_unref (media); + + gst_rtsp_url_free (url); + g_object_unref (factory); + g_object_unref (pool); + + gst_rtsp_thread_pool_cleanup (); +} + +GST_END_TEST; + +static Suite * +rtspmedia_suite (void) +{ + Suite *s = suite_create ("rtspmedia"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_set_timeout (tc, 20); + tcase_add_test (tc, test_launch); + tcase_add_test (tc, test_media); + tcase_add_test (tc, test_media_prepare); + tcase_add_test (tc, test_media_dyn_prepare); + tcase_add_test (tc, test_media_prepare_port_alloc_fail); + tcase_add_test (tc, test_media_take_pipeline); + tcase_add_test (tc, test_media_reset); + + return s; +} + +GST_CHECK_MAIN (rtspmedia); diff --git a/tests/check/gst/mediafactory.c b/tests/check/gst/mediafactory.c new file mode 100644 index 0000000..b6b250b --- /dev/null +++ b/tests/check/gst/mediafactory.c @@ -0,0 +1,336 @@ +/* GStreamer + * Copyright (C) 2012 Wim Taymans + * + * 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. + */ + +#include + +#include + +GST_START_TEST (test_parse_error) +{ + GstRTSPMediaFactory *factory; + GstRTSPUrl *url; + + factory = gst_rtsp_media_factory_new (); + + gst_rtsp_media_factory_set_launch (factory, "foo"); + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + ASSERT_CRITICAL (gst_rtsp_media_factory_create_element (factory, url)); + ASSERT_CRITICAL (gst_rtsp_media_factory_construct (factory, url)); + + gst_rtsp_url_free (url); + g_object_unref (factory); +} + +GST_END_TEST; + +GST_START_TEST (test_launch) +{ + GstRTSPMediaFactory *factory; + GstElement *element; + GstRTSPUrl *url; + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + + element = gst_rtsp_media_factory_create_element (factory, url); + fail_unless (GST_IS_BIN (element)); + fail_if (GST_IS_PIPELINE (element)); + gst_object_unref (element); + + gst_rtsp_url_free (url); + g_object_unref (factory); +} + +GST_END_TEST; + +GST_START_TEST (test_launch_construct) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media, *media2; + GstRTSPUrl *url; + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + media2 = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media2)); + fail_if (media == media2); + + g_object_unref (media); + g_object_unref (media2); + + gst_rtsp_url_free (url); + g_object_unref (factory); +} + +GST_END_TEST; + +GST_START_TEST (test_shared) +{ + GstRTSPMediaFactory *factory; + GstElement *element; + GstRTSPMedia *media, *media2; + GstRTSPUrl *url; + + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_shared (factory, TRUE); + fail_unless (gst_rtsp_media_factory_is_shared (factory)); + + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + + element = gst_rtsp_media_factory_create_element (factory, url); + fail_unless (GST_IS_BIN (element)); + fail_if (GST_IS_PIPELINE (element)); + gst_object_unref (element); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + media2 = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media2)); + fail_unless (media == media2); + + g_object_unref (media); + g_object_unref (media2); + + gst_rtsp_url_free (url); + g_object_unref (factory); +} + +GST_END_TEST; + +GST_START_TEST (test_addresspool) +{ + GstRTSPMediaFactory *factory; + GstElement *element; + GstRTSPMedia *media; + GstRTSPUrl *url; + GstRTSPAddressPool *pool, *tmppool; + GstRTSPStream *stream; + GstRTSPAddress *addr; + + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_shared (factory, TRUE); + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 " + " audiotestsrc ! audioconvert ! rtpL16pay name=pay1 )"); + + pool = gst_rtsp_address_pool_new (); + fail_unless (gst_rtsp_address_pool_add_range (pool, + "233.252.0.1", "233.252.0.1", 5000, 5001, 3)); + + gst_rtsp_media_factory_set_address_pool (factory, pool); + + tmppool = gst_rtsp_media_factory_get_address_pool (factory); + fail_unless (pool == tmppool); + g_object_unref (tmppool); + + element = gst_rtsp_media_factory_create_element (factory, url); + fail_unless (GST_IS_BIN (element)); + fail_if (GST_IS_PIPELINE (element)); + gst_object_unref (element); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + tmppool = gst_rtsp_media_get_address_pool (media); + fail_unless (pool == tmppool); + g_object_unref (tmppool); + + fail_unless (gst_rtsp_media_n_streams (media) == 2); + + stream = gst_rtsp_media_get_stream (media, 0); + fail_unless (stream != NULL); + + tmppool = gst_rtsp_stream_get_address_pool (stream); + fail_unless (pool == tmppool); + g_object_unref (tmppool); + + addr = gst_rtsp_stream_get_multicast_address (stream, G_SOCKET_FAMILY_IPV4); + fail_unless (addr != NULL); + fail_unless (addr->port == 5000); + fail_unless (addr->n_ports == 2); + fail_unless (addr->ttl == 3); + gst_rtsp_address_free (addr); + + stream = gst_rtsp_media_get_stream (media, 1); + fail_unless (stream != NULL); + + tmppool = gst_rtsp_stream_get_address_pool (stream); + fail_unless (pool == tmppool); + g_object_unref (tmppool); + + addr = gst_rtsp_stream_get_multicast_address (stream, G_SOCKET_FAMILY_IPV4); + fail_unless (addr == NULL); + + + g_object_unref (media); + + g_object_unref (pool); + gst_rtsp_url_free (url); + g_object_unref (factory); +} + +GST_END_TEST; + +GST_START_TEST (test_permissions) +{ + GstRTSPMediaFactory *factory; + GstRTSPPermissions *perms; + GstRTSPMedia *media; + GstRTSPUrl *url; + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + + gst_rtsp_media_factory_add_role (factory, "admin", + "media.factory.access", G_TYPE_BOOLEAN, TRUE, + "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL); + + perms = gst_rtsp_media_factory_get_permissions (factory); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "admin", + "media.factory.access")); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "admin", + "media.factory.construct")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "missing", + "media.factory.access")); + gst_rtsp_permissions_unref (perms); + + perms = gst_rtsp_permissions_new (); + gst_rtsp_permissions_add_role (perms, "user", + "media.factory.access", G_TYPE_BOOLEAN, TRUE, + "media.factory.construct", G_TYPE_BOOLEAN, FALSE, NULL); + gst_rtsp_media_factory_set_permissions (factory, perms); + gst_rtsp_permissions_unref (perms); + + perms = gst_rtsp_media_factory_get_permissions (factory); + fail_if (gst_rtsp_permissions_is_allowed (perms, "admin", + "media.factory.access")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "admin", + "media.factory.construct")); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "user", + "media.factory.access")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "user", + "media.factory.construct")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "missing", + "media.factory.access")); + gst_rtsp_permissions_unref (perms); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + perms = gst_rtsp_media_get_permissions (media); + fail_if (gst_rtsp_permissions_is_allowed (perms, "admin", + "media.factory.access")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "admin", + "media.factory.construct")); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "user", + "media.factory.access")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "user", + "media.factory.construct")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "missing", + "media.factory.access")); + gst_rtsp_permissions_unref (perms); + g_object_unref (media); + + gst_rtsp_url_free (url); + g_object_unref (factory); +} + +GST_END_TEST; + +GST_START_TEST (test_reset) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url; + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + gst_rtsp_url_parse ("rtsp://localhost:8554/test", &url); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + fail_if (gst_rtsp_media_get_suspend_mode (media) != + GST_RTSP_SUSPEND_MODE_NONE); + g_object_unref (media); + + gst_rtsp_media_factory_set_suspend_mode (factory, + GST_RTSP_SUSPEND_MODE_RESET); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + fail_if (gst_rtsp_media_get_suspend_mode (media) != + GST_RTSP_SUSPEND_MODE_RESET); + g_object_unref (media); + + gst_rtsp_url_free (url); + g_object_unref (factory); +} + +GST_END_TEST; + +static Suite * +rtspmediafactory_suite (void) +{ + Suite *s = suite_create ("rtspmediafactory"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_set_timeout (tc, 20); + tcase_add_test (tc, test_parse_error); + tcase_add_test (tc, test_launch); + tcase_add_test (tc, test_launch_construct); + tcase_add_test (tc, test_shared); + tcase_add_test (tc, test_addresspool); + tcase_add_test (tc, test_permissions); + tcase_add_test (tc, test_reset); + + return s; +} + +GST_CHECK_MAIN (rtspmediafactory); diff --git a/tests/check/gst/mountpoints.c b/tests/check/gst/mountpoints.c new file mode 100644 index 0000000..31a223e --- /dev/null +++ b/tests/check/gst/mountpoints.c @@ -0,0 +1,147 @@ +/* GStreamer + * Copyright (C) 2012 Wim Taymans + * + * 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. + */ + +#include + +#include + +GST_START_TEST (test_create) +{ + GstRTSPMountPoints *mounts; + GstRTSPUrl *url, *url2; + GstRTSPMediaFactory *factory; + + mounts = gst_rtsp_mount_points_new (); + + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test", + &url) == GST_RTSP_OK); + fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test2", + &url2) == GST_RTSP_OK); + + fail_unless (gst_rtsp_mount_points_match (mounts, url->abspath, + NULL) == NULL); + + factory = gst_rtsp_media_factory_new (); + gst_rtsp_mount_points_add_factory (mounts, "/test", factory); + + fail_unless (gst_rtsp_mount_points_match (mounts, url->abspath, + NULL) == factory); + g_object_unref (factory); + fail_unless (gst_rtsp_mount_points_match (mounts, url2->abspath, + NULL) == NULL); + + gst_rtsp_mount_points_remove_factory (mounts, "/test"); + + fail_unless (gst_rtsp_mount_points_match (mounts, url->abspath, + NULL) == NULL); + fail_unless (gst_rtsp_mount_points_match (mounts, url2->abspath, + NULL) == NULL); + + gst_rtsp_url_free (url); + gst_rtsp_url_free (url2); + + g_object_unref (mounts); +} + +GST_END_TEST; + +static const gchar *paths[] = { + "/test", + "/booz/fooz", + "/booz/foo/zoop", + "/tark/bar", + "/tark/bar/baz", + "/tark/bar/baz/t", + "/boozop", +}; + +GST_START_TEST (test_match) +{ + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *f[G_N_ELEMENTS (paths)], *tmp; + gint i, matched; + + mounts = gst_rtsp_mount_points_new (); + + for (i = 0; i < G_N_ELEMENTS (paths); i++) { + f[i] = gst_rtsp_media_factory_new (); + gst_rtsp_mount_points_add_factory (mounts, paths[i], f[i]); + } + + tmp = gst_rtsp_mount_points_match (mounts, "/test", &matched); + fail_unless (tmp == f[0]); + fail_unless (matched == 5); + g_object_unref (tmp); + tmp = gst_rtsp_mount_points_match (mounts, "/test/stream=1", &matched); + fail_unless (tmp == f[0]); + fail_unless (matched == 5); + g_object_unref (tmp); + tmp = gst_rtsp_mount_points_match (mounts, "/booz", &matched); + fail_unless (tmp == NULL); + tmp = gst_rtsp_mount_points_match (mounts, "/booz/foo", &matched); + fail_unless (tmp == NULL); + tmp = gst_rtsp_mount_points_match (mounts, "/booz/fooz", &matched); + fail_unless (tmp == f[1]); + fail_unless (matched == 10); + g_object_unref (tmp); + tmp = gst_rtsp_mount_points_match (mounts, "/booz/fooz/zoo", &matched); + fail_unless (tmp == f[1]); + fail_unless (matched == 10); + g_object_unref (tmp); + tmp = gst_rtsp_mount_points_match (mounts, "/booz/foo/zoop", &matched); + fail_unless (tmp == f[2]); + fail_unless (matched == 14); + g_object_unref (tmp); + tmp = gst_rtsp_mount_points_match (mounts, "/tark/bar", &matched); + fail_unless (tmp == f[3]); + fail_unless (matched == 9); + g_object_unref (tmp); + tmp = gst_rtsp_mount_points_match (mounts, "/tark/bar/boo", &matched); + fail_unless (tmp == f[3]); + fail_unless (matched == 9); + g_object_unref (tmp); + tmp = gst_rtsp_mount_points_match (mounts, "/tark/bar/ba", &matched); + fail_unless (tmp == f[3]); + fail_unless (matched == 9); + g_object_unref (tmp); + tmp = gst_rtsp_mount_points_match (mounts, "/tark/bar/baz", &matched); + fail_unless (tmp == f[4]); + fail_unless (matched == 13); + g_object_unref (tmp); + + g_object_unref (mounts); +} + +GST_END_TEST; + +static Suite * +rtspmountpoints_suite (void) +{ + Suite *s = suite_create ("rtspmountpoints"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_set_timeout (tc, 20); + tcase_add_test (tc, test_create); + tcase_add_test (tc, test_match); + + return s; +} + +GST_CHECK_MAIN (rtspmountpoints); diff --git a/tests/check/gst/permissions.c b/tests/check/gst/permissions.c new file mode 100644 index 0000000..0dcf770 --- /dev/null +++ b/tests/check/gst/permissions.c @@ -0,0 +1,107 @@ +/* GStreamer + * Copyright (C) 2013 Sebastian Rasmussen + * + * 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. + */ + +#include + +#include + +GST_START_TEST (test_permissions) +{ + GstRTSPPermissions *perms; + GstRTSPPermissions *copy; + + perms = gst_rtsp_permissions_new (); + fail_if (gst_rtsp_permissions_is_allowed (perms, "missing", "permission1")); + gst_rtsp_permissions_unref (perms); + + perms = gst_rtsp_permissions_new (); + gst_rtsp_permissions_add_role (perms, "user", + "permission1", G_TYPE_BOOLEAN, TRUE, + "permission2", G_TYPE_BOOLEAN, FALSE, NULL); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "user", "permission1")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "user", "permission2")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "user", "missing")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "missing", "permission1")); + copy = GST_RTSP_PERMISSIONS (gst_mini_object_copy (GST_MINI_OBJECT (perms))); + gst_rtsp_permissions_unref (perms); + fail_unless (gst_rtsp_permissions_is_allowed (copy, "user", "permission1")); + fail_if (gst_rtsp_permissions_is_allowed (copy, "user", "permission2")); + gst_rtsp_permissions_unref (copy); + + perms = gst_rtsp_permissions_new (); + gst_rtsp_permissions_add_role (perms, "admin", + "permission1", G_TYPE_BOOLEAN, TRUE, + "permission2", G_TYPE_BOOLEAN, TRUE, NULL); + gst_rtsp_permissions_add_role (perms, "user", + "permission1", G_TYPE_BOOLEAN, TRUE, + "permission2", G_TYPE_BOOLEAN, FALSE, NULL); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "admin", "permission1")); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "admin", "permission2")); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "user", "permission1")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "user", "permission2")); + gst_rtsp_permissions_unref (perms); + + perms = gst_rtsp_permissions_new (); + gst_rtsp_permissions_add_role (perms, "user", + "permission1", G_TYPE_BOOLEAN, TRUE, + "permission2", G_TYPE_BOOLEAN, FALSE, NULL); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "user", "permission1")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "user", "permission2")); + gst_rtsp_permissions_add_role (perms, "user", + "permission1", G_TYPE_BOOLEAN, FALSE, + "permission2", G_TYPE_BOOLEAN, TRUE, NULL); + fail_if (gst_rtsp_permissions_is_allowed (perms, "user", "permission1")); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "user", "permission2")); + gst_rtsp_permissions_unref (perms); + + perms = gst_rtsp_permissions_new (); + gst_rtsp_permissions_add_role (perms, "admin", + "permission1", G_TYPE_BOOLEAN, TRUE, + "permission2", G_TYPE_BOOLEAN, TRUE, NULL); + gst_rtsp_permissions_add_role (perms, "user", + "permission1", G_TYPE_BOOLEAN, TRUE, + "permission2", G_TYPE_BOOLEAN, FALSE, NULL); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "admin", "permission1")); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "admin", "permission2")); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "user", "permission1")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "user", "permission2")); + gst_rtsp_permissions_remove_role (perms, "user"); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "admin", "permission1")); + fail_unless (gst_rtsp_permissions_is_allowed (perms, "admin", "permission2")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "user", "permission1")); + fail_if (gst_rtsp_permissions_is_allowed (perms, "user", "permission2")); + gst_rtsp_permissions_unref (perms); +} + +GST_END_TEST; + +static Suite * +rtsppermissions_suite (void) +{ + Suite *s = suite_create ("rtsppermissions"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_set_timeout (tc, 20); + tcase_add_test (tc, test_permissions); + + return s; +} + +GST_CHECK_MAIN (rtsppermissions); diff --git a/tests/check/gst/rtspserver.c b/tests/check/gst/rtspserver.c new file mode 100644 index 0000000..28910f7 --- /dev/null +++ b/tests/check/gst/rtspserver.c @@ -0,0 +1,1454 @@ +/* GStreamer + * + * unit test for GstRTSPServer + * + * Copyright (C) 2012 Axis Communications + * @author David Svensson Fors + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include + +#include "rtsp-server.h" + +#define VIDEO_PIPELINE "videotestsrc ! " \ + "video/x-raw,width=352,height=288 ! " \ + "rtpgstpay name=pay0 pt=96" +#define AUDIO_PIPELINE "audiotestsrc ! " \ + "audio/x-raw,rate=8000 ! " \ + "rtpgstpay name=pay1 pt=97" + +#define TEST_MOUNT_POINT "/test" +#define TEST_PROTO "RTP/AVP" +#define TEST_ENCODING "X-GST" +#define TEST_CLOCK_RATE "90000" + +/* tested rtsp server */ +static GstRTSPServer *server = NULL; + +/* tcp port that the test server listens for rtsp requests on */ +static gint test_port = 0; + +/* id of the server's source within the GMainContext */ +static guint source_id; + +/* iterate the default main loop until there are no events to dispatch */ +static void +iterate (void) +{ + while (g_main_context_iteration (NULL, FALSE)) { + GST_DEBUG ("iteration"); + } +} + +static void +get_client_ports_full (GstRTSPRange * range, GSocket ** rtp_socket, + GSocket ** rtcp_socket) +{ + GSocket *rtp = NULL; + GSocket *rtcp = NULL; + gint rtp_port = 0; + gint rtcp_port; + GInetAddress *anyaddr = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4); + GSocketAddress *sockaddr; + gboolean bound; + + for (;;) { + if (rtp_port != 0) + rtp_port += 2; + + rtp = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, + G_SOCKET_PROTOCOL_UDP, NULL); + fail_unless (rtp != NULL); + + sockaddr = g_inet_socket_address_new (anyaddr, rtp_port); + fail_unless (sockaddr != NULL); + bound = g_socket_bind (rtp, sockaddr, FALSE, NULL); + g_object_unref (sockaddr); + if (!bound) { + g_object_unref (rtp); + continue; + } + + sockaddr = g_socket_get_local_address (rtp, NULL); + fail_unless (sockaddr != NULL && G_IS_INET_SOCKET_ADDRESS (sockaddr)); + rtp_port = + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (sockaddr)); + g_object_unref (sockaddr); + + if (rtp_port % 2 != 0) { + rtp_port += 1; + g_object_unref (rtp); + continue; + } + + rtcp_port = rtp_port + 1; + + rtcp = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, + G_SOCKET_PROTOCOL_UDP, NULL); + fail_unless (rtcp != NULL); + + sockaddr = g_inet_socket_address_new (anyaddr, rtcp_port); + fail_unless (sockaddr != NULL); + bound = g_socket_bind (rtcp, sockaddr, FALSE, NULL); + g_object_unref (sockaddr); + if (!bound) { + g_object_unref (rtp); + g_object_unref (rtcp); + continue; + } + + sockaddr = g_socket_get_local_address (rtcp, NULL); + fail_unless (sockaddr != NULL && G_IS_INET_SOCKET_ADDRESS (sockaddr)); + fail_unless (rtcp_port == + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (sockaddr))); + g_object_unref (sockaddr); + + break; + } + + range->min = rtp_port; + range->max = rtcp_port; + if (rtp_socket) + *rtp_socket = rtp; + else + g_object_unref (rtp); + if (rtcp_socket) + *rtcp_socket = rtcp; + else + g_object_unref (rtcp); + GST_DEBUG ("client_port=%d-%d", range->min, range->max); + g_object_unref (anyaddr); +} + +/* get a free rtp/rtcp client port pair */ +static void +get_client_ports (GstRTSPRange * range) +{ + get_client_ports_full (range, NULL, NULL); +} + +/* start the tested rtsp server */ +static void +start_server (void) +{ + GstRTSPMountPoints *mounts; + gchar *service; + GstRTSPMediaFactory *factory; + + mounts = gst_rtsp_server_get_mount_points (server); + + factory = gst_rtsp_media_factory_new (); + + gst_rtsp_media_factory_set_launch (factory, + "( " VIDEO_PIPELINE " " AUDIO_PIPELINE " )"); + gst_rtsp_mount_points_add_factory (mounts, TEST_MOUNT_POINT, factory); + g_object_unref (mounts); + + /* set port to any */ + gst_rtsp_server_set_service (server, "0"); + + /* attach to default main context */ + source_id = gst_rtsp_server_attach (server, NULL); + fail_if (source_id == 0); + + /* get port */ + service = gst_rtsp_server_get_service (server); + test_port = atoi (service); + fail_unless (test_port != 0); + g_free (service); + + GST_DEBUG ("rtsp server listening on port %d", test_port); +} + +/* stop the tested rtsp server */ +static void +stop_server (void) +{ + g_source_remove (source_id); + source_id = 0; + + GST_DEBUG ("rtsp server stopped"); +} + +/* create an rtsp connection to the server on test_port */ +static GstRTSPConnection * +connect_to_server (gint port, const gchar * mount_point) +{ + GstRTSPConnection *conn = NULL; + gchar *address; + gchar *uri_string; + GstRTSPUrl *url = NULL; + + address = gst_rtsp_server_get_address (server); + uri_string = g_strdup_printf ("rtsp://%s:%d%s", address, port, mount_point); + g_free (address); + fail_unless (gst_rtsp_url_parse (uri_string, &url) == GST_RTSP_OK); + g_free (uri_string); + + fail_unless (gst_rtsp_connection_create (url, &conn) == GST_RTSP_OK); + gst_rtsp_url_free (url); + + fail_unless (gst_rtsp_connection_connect (conn, NULL) == GST_RTSP_OK); + + return conn; +} + +/* create an rtsp request */ +static GstRTSPMessage * +create_request (GstRTSPConnection * conn, GstRTSPMethod method, + const gchar * control) +{ + GstRTSPMessage *request = NULL; + gchar *base_uri; + gchar *full_uri; + + base_uri = gst_rtsp_url_get_request_uri (gst_rtsp_connection_get_url (conn)); + full_uri = g_strdup_printf ("%s/%s", base_uri, control ? control : ""); + g_free (base_uri); + if (gst_rtsp_message_new_request (&request, method, full_uri) != GST_RTSP_OK) { + GST_DEBUG ("failed to create request object"); + g_free (full_uri); + return NULL; + } + g_free (full_uri); + return request; +} + +/* send an rtsp request */ +static gboolean +send_request (GstRTSPConnection * conn, GstRTSPMessage * request) +{ + if (gst_rtsp_connection_send (conn, request, NULL) != GST_RTSP_OK) { + GST_DEBUG ("failed to send request"); + return FALSE; + } + return TRUE; +} + +/* read rtsp response. response must be freed by the caller */ +static GstRTSPMessage * +read_response (GstRTSPConnection * conn) +{ + GstRTSPMessage *response = NULL; + + if (gst_rtsp_message_new (&response) != GST_RTSP_OK) { + GST_DEBUG ("failed to create response object"); + return NULL; + } + if (gst_rtsp_connection_receive (conn, response, NULL) != GST_RTSP_OK) { + GST_DEBUG ("failed to read response"); + gst_rtsp_message_free (response); + return NULL; + } + fail_unless (gst_rtsp_message_get_type (response) == + GST_RTSP_MESSAGE_RESPONSE); + return response; +} + +/* send an rtsp request and receive response. gchar** parameters are out + * parameters that have to be freed by the caller */ +static GstRTSPStatusCode +do_request_full (GstRTSPConnection * conn, GstRTSPMethod method, + const gchar * control, const gchar * session_in, const gchar * transport_in, + const gchar * range_in, const gchar * require_in, + gchar ** content_type, gchar ** content_base, gchar ** body, + gchar ** session_out, gchar ** transport_out, gchar ** range_out, + gchar ** unsupported_out) +{ + GstRTSPMessage *request; + GstRTSPMessage *response; + GstRTSPStatusCode code; + gchar *value; + + /* create request */ + request = create_request (conn, method, control); + + /* add headers */ + if (session_in) { + gst_rtsp_message_add_header (request, GST_RTSP_HDR_SESSION, session_in); + } + if (transport_in) { + gst_rtsp_message_add_header (request, GST_RTSP_HDR_TRANSPORT, transport_in); + } + if (range_in) { + gst_rtsp_message_add_header (request, GST_RTSP_HDR_RANGE, range_in); + } + if (require_in) { + gst_rtsp_message_add_header (request, GST_RTSP_HDR_REQUIRE, require_in); + } + + /* send request */ + fail_unless (send_request (conn, request)); + gst_rtsp_message_free (request); + + iterate (); + + /* read response */ + response = read_response (conn); + + /* check status line */ + gst_rtsp_message_parse_response (response, &code, NULL, NULL); + if (code != GST_RTSP_STS_OK) { + if (unsupported_out != NULL && code == GST_RTSP_STS_OPTION_NOT_SUPPORTED) { + gst_rtsp_message_get_header (response, GST_RTSP_HDR_UNSUPPORTED, + &value, 0); + *unsupported_out = g_strdup (value); + } + gst_rtsp_message_free (response); + return code; + } + + /* get information from response */ + if (content_type) { + gst_rtsp_message_get_header (response, GST_RTSP_HDR_CONTENT_TYPE, + &value, 0); + *content_type = g_strdup (value); + } + if (content_base) { + gst_rtsp_message_get_header (response, GST_RTSP_HDR_CONTENT_BASE, + &value, 0); + *content_base = g_strdup (value); + } + if (body) { + *body = g_malloc (response->body_size + 1); + strncpy (*body, (gchar *) response->body, response->body_size); + } + if (session_out) { + gst_rtsp_message_get_header (response, GST_RTSP_HDR_SESSION, &value, 0); + + value = g_strdup (value); + + /* Remove the timeout */ + if (value) { + char *pos = strchr (value, ';'); + if (pos) + *pos = 0; + } + if (session_in) { + /* check that we got the same session back */ + fail_unless (!g_strcmp0 (value, session_in)); + } + *session_out = value; + } + if (transport_out) { + gst_rtsp_message_get_header (response, GST_RTSP_HDR_TRANSPORT, &value, 0); + *transport_out = g_strdup (value); + } + if (range_out) { + gst_rtsp_message_get_header (response, GST_RTSP_HDR_RANGE, &value, 0); + *range_out = g_strdup (value); + } + + gst_rtsp_message_free (response); + return code; +} + +/* send an rtsp request and receive response. gchar** parameters are out + * parameters that have to be freed by the caller */ +static GstRTSPStatusCode +do_request (GstRTSPConnection * conn, GstRTSPMethod method, + const gchar * control, const gchar * session_in, + const gchar * transport_in, const gchar * range_in, + gchar ** content_type, gchar ** content_base, gchar ** body, + gchar ** session_out, gchar ** transport_out, gchar ** range_out) +{ + return do_request_full (conn, method, control, session_in, transport_in, + range_in, NULL, content_type, content_base, body, session_out, + transport_out, range_out, NULL); +} + +/* send an rtsp request with a method and a session, and receive response */ +static GstRTSPStatusCode +do_simple_request (GstRTSPConnection * conn, GstRTSPMethod method, + const gchar * session) +{ + return do_request (conn, method, NULL, session, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); +} + +/* send a DESCRIBE request and receive response. returns a received + * GstSDPMessage that must be freed by the caller */ +static GstSDPMessage * +do_describe (GstRTSPConnection * conn, const gchar * mount_point) +{ + GstSDPMessage *sdp_message; + gchar *content_type; + gchar *content_base; + gchar *body; + gchar *address; + gchar *expected_content_base; + + /* send DESCRIBE request */ + fail_unless (do_request (conn, GST_RTSP_DESCRIBE, NULL, NULL, NULL, NULL, + &content_type, &content_base, &body, NULL, NULL, NULL) == + GST_RTSP_STS_OK); + + /* check response values */ + fail_unless (!g_strcmp0 (content_type, "application/sdp")); + address = gst_rtsp_server_get_address (server); + expected_content_base = + g_strdup_printf ("rtsp://%s:%d%s/", address, test_port, mount_point); + fail_unless (!g_strcmp0 (content_base, expected_content_base)); + + /* create sdp message */ + fail_unless (gst_sdp_message_new (&sdp_message) == GST_SDP_OK); + fail_unless (gst_sdp_message_parse_buffer ((guint8 *) body, + strlen (body), sdp_message) == GST_SDP_OK); + + /* clean up */ + g_free (content_type); + g_free (content_base); + g_free (body); + g_free (address); + g_free (expected_content_base); + + return sdp_message; +} + +/* send a SETUP request and receive response. if *session is not NULL, + * it is used in the request. otherwise, *session is set to a returned + * session string that must be freed by the caller. the returned + * transport must be freed by the caller. */ +static GstRTSPStatusCode +do_setup_full (GstRTSPConnection * conn, const gchar * control, + const GstRTSPRange * client_ports, const gchar * require, gchar ** session, + GstRTSPTransport ** transport, gchar ** unsupported) +{ + GstRTSPStatusCode code; + gchar *session_in = NULL; + gchar *transport_string_in = NULL; + gchar **session_out = NULL; + gchar *transport_string_out = NULL; + + /* prepare and send SETUP request */ + if (session) { + if (*session) { + session_in = *session; + } else { + session_out = session; + } + } + transport_string_in = + g_strdup_printf (TEST_PROTO ";unicast;client_port=%d-%d", + client_ports->min, client_ports->max); + code = + do_request_full (conn, GST_RTSP_SETUP, control, session_in, + transport_string_in, NULL, require, NULL, NULL, NULL, session_out, + &transport_string_out, NULL, unsupported); + g_free (transport_string_in); + + if (transport_string_out) { + /* create transport */ + fail_unless (gst_rtsp_transport_new (transport) == GST_RTSP_OK); + fail_unless (gst_rtsp_transport_parse (transport_string_out, + *transport) == GST_RTSP_OK); + g_free (transport_string_out); + } + GST_INFO ("code=%d", code); + return code; +} + +/* send a SETUP request and receive response. if *session is not NULL, + * it is used in the request. otherwise, *session is set to a returned + * session string that must be freed by the caller. the returned + * transport must be freed by the caller. */ +static GstRTSPStatusCode +do_setup (GstRTSPConnection * conn, const gchar * control, + const GstRTSPRange * client_ports, gchar ** session, + GstRTSPTransport ** transport) +{ + return do_setup_full (conn, control, client_ports, NULL, session, transport, + NULL); +} + +/* fixture setup function */ +static void +setup (void) +{ + server = gst_rtsp_server_new (); +} + +/* fixture clean-up function */ +static void +teardown (void) +{ + if (server) { + g_object_unref (server); + server = NULL; + } + test_port = 0; +} + +GST_START_TEST (test_connect) +{ + GstRTSPConnection *conn; + + start_server (); + + /* connect to server */ + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + /* clean up */ + gst_rtsp_connection_free (conn); + stop_server (); + + /* iterate so the clean-up can finish */ + iterate (); +} + +GST_END_TEST; + +GST_START_TEST (test_describe) +{ + GstRTSPConnection *conn; + GstSDPMessage *sdp_message = NULL; + const GstSDPMedia *sdp_media; + gint32 format; + gchar *expected_rtpmap; + const gchar *rtpmap; + const gchar *control_video; + const gchar *control_audio; + + start_server (); + + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + /* send DESCRIBE request */ + sdp_message = do_describe (conn, TEST_MOUNT_POINT); + + fail_unless (gst_sdp_message_medias_len (sdp_message) == 2); + + /* check video sdp */ + sdp_media = gst_sdp_message_get_media (sdp_message, 0); + fail_unless (!g_strcmp0 (gst_sdp_media_get_proto (sdp_media), TEST_PROTO)); + fail_unless (gst_sdp_media_formats_len (sdp_media) == 1); + sscanf (gst_sdp_media_get_format (sdp_media, 0), "%" G_GINT32_FORMAT, + &format); + expected_rtpmap = + g_strdup_printf ("%d " TEST_ENCODING "/" TEST_CLOCK_RATE, format); + rtpmap = gst_sdp_media_get_attribute_val (sdp_media, "rtpmap"); + fail_unless (!g_strcmp0 (rtpmap, expected_rtpmap)); + g_free (expected_rtpmap); + control_video = gst_sdp_media_get_attribute_val (sdp_media, "control"); + fail_unless (!g_strcmp0 (control_video, "stream=0")); + + /* check audio sdp */ + sdp_media = gst_sdp_message_get_media (sdp_message, 1); + fail_unless (!g_strcmp0 (gst_sdp_media_get_proto (sdp_media), TEST_PROTO)); + fail_unless (gst_sdp_media_formats_len (sdp_media) == 1); + sscanf (gst_sdp_media_get_format (sdp_media, 0), "%" G_GINT32_FORMAT, + &format); + expected_rtpmap = + g_strdup_printf ("%d " TEST_ENCODING "/" TEST_CLOCK_RATE, format); + rtpmap = gst_sdp_media_get_attribute_val (sdp_media, "rtpmap"); + fail_unless (!g_strcmp0 (rtpmap, expected_rtpmap)); + g_free (expected_rtpmap); + control_audio = gst_sdp_media_get_attribute_val (sdp_media, "control"); + fail_unless (!g_strcmp0 (control_audio, "stream=1")); + + /* clean up and iterate so the clean-up can finish */ + gst_sdp_message_free (sdp_message); + gst_rtsp_connection_free (conn); + stop_server (); + iterate (); +} + +GST_END_TEST; + +GST_START_TEST (test_describe_non_existing_mount_point) +{ + GstRTSPConnection *conn; + + start_server (); + + /* send DESCRIBE request for a non-existing mount point + * and check that we get a 404 Not Found */ + conn = connect_to_server (test_port, "/non-existing"); + fail_unless (do_simple_request (conn, GST_RTSP_DESCRIBE, NULL) + == GST_RTSP_STS_NOT_FOUND); + + /* clean up and iterate so the clean-up can finish */ + gst_rtsp_connection_free (conn); + stop_server (); + iterate (); +} + +GST_END_TEST; + +GST_START_TEST (test_setup) +{ + GstRTSPConnection *conn; + GstSDPMessage *sdp_message = NULL; + const GstSDPMedia *sdp_media; + const gchar *video_control; + const gchar *audio_control; + GstRTSPRange client_ports; + gchar *session = NULL; + GstRTSPTransport *video_transport = NULL; + GstRTSPTransport *audio_transport = NULL; + + start_server (); + + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + sdp_message = do_describe (conn, TEST_MOUNT_POINT); + + /* get control strings from DESCRIBE response */ + fail_unless (gst_sdp_message_medias_len (sdp_message) == 2); + sdp_media = gst_sdp_message_get_media (sdp_message, 0); + video_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + sdp_media = gst_sdp_message_get_media (sdp_message, 1); + audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + + get_client_ports (&client_ports); + + /* send SETUP request for video */ + fail_unless (do_setup (conn, video_control, &client_ports, &session, + &video_transport) == GST_RTSP_STS_OK); + GST_DEBUG ("set up video %s, got session '%s'", video_control, session); + + /* check response from SETUP */ + fail_unless (video_transport->trans == GST_RTSP_TRANS_RTP); + fail_unless (video_transport->profile == GST_RTSP_PROFILE_AVP); + fail_unless (video_transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP); + fail_unless (video_transport->mode_play); + gst_rtsp_transport_free (video_transport); + + /* send SETUP request for audio */ + fail_unless (do_setup (conn, audio_control, &client_ports, &session, + &audio_transport) == GST_RTSP_STS_OK); + GST_DEBUG ("set up audio %s with session '%s'", audio_control, session); + + /* check response from SETUP */ + fail_unless (audio_transport->trans == GST_RTSP_TRANS_RTP); + fail_unless (audio_transport->profile == GST_RTSP_PROFILE_AVP); + fail_unless (audio_transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP); + fail_unless (audio_transport->mode_play); + gst_rtsp_transport_free (audio_transport); + + /* send TEARDOWN request and check that we get 200 OK */ + fail_unless (do_simple_request (conn, GST_RTSP_TEARDOWN, + session) == GST_RTSP_STS_OK); + + /* clean up and iterate so the clean-up can finish */ + g_free (session); + gst_sdp_message_free (sdp_message); + gst_rtsp_connection_free (conn); + stop_server (); + iterate (); +} + +GST_END_TEST; + +GST_START_TEST (test_setup_with_require_header) +{ + GstRTSPConnection *conn; + GstSDPMessage *sdp_message = NULL; + const GstSDPMedia *sdp_media; + const gchar *video_control; + GstRTSPRange client_ports; + gchar *session = NULL; + gchar *unsupported = NULL; + GstRTSPTransport *video_transport = NULL; + + start_server (); + + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + sdp_message = do_describe (conn, TEST_MOUNT_POINT); + + /* get control strings from DESCRIBE response */ + fail_unless (gst_sdp_message_medias_len (sdp_message) == 2); + sdp_media = gst_sdp_message_get_media (sdp_message, 0); + video_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + + get_client_ports (&client_ports); + + /* send SETUP request for video, with single Require header */ + fail_unless_equals_int (do_setup_full (conn, video_control, &client_ports, + "funky-feature", &session, &video_transport, &unsupported), + GST_RTSP_STS_OPTION_NOT_SUPPORTED); + fail_unless_equals_string (unsupported, "funky-feature"); + g_free (unsupported); + unsupported = NULL; + + /* send SETUP request for video, with multiple Require headers */ + fail_unless_equals_int (do_setup_full (conn, video_control, &client_ports, + "funky-feature, foo-bar, superburst", &session, &video_transport, + &unsupported), GST_RTSP_STS_OPTION_NOT_SUPPORTED); + fail_unless_equals_string (unsupported, "funky-feature, foo-bar, superburst"); + g_free (unsupported); + unsupported = NULL; + + /* ok, just do a normal setup then (make sure that still works) */ + fail_unless_equals_int (do_setup (conn, video_control, &client_ports, + &session, &video_transport), GST_RTSP_STS_OK); + + GST_DEBUG ("set up video %s, got session '%s'", video_control, session); + + /* check response from SETUP */ + fail_unless (video_transport->trans == GST_RTSP_TRANS_RTP); + fail_unless (video_transport->profile == GST_RTSP_PROFILE_AVP); + fail_unless (video_transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP); + fail_unless (video_transport->mode_play); + gst_rtsp_transport_free (video_transport); + + /* send TEARDOWN request and check that we get 200 OK */ + fail_unless (do_simple_request (conn, GST_RTSP_TEARDOWN, + session) == GST_RTSP_STS_OK); + + /* clean up and iterate so the clean-up can finish */ + g_free (session); + gst_sdp_message_free (sdp_message); + gst_rtsp_connection_free (conn); + stop_server (); + iterate (); +} + +GST_END_TEST; + +GST_START_TEST (test_setup_non_existing_stream) +{ + GstRTSPConnection *conn; + GstRTSPRange client_ports; + + start_server (); + + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + get_client_ports (&client_ports); + + /* send SETUP request with a non-existing stream and check that we get a + * 404 Not Found */ + fail_unless (do_setup (conn, "stream=7", &client_ports, NULL, + NULL) == GST_RTSP_STS_NOT_FOUND); + + /* clean up and iterate so the clean-up can finish */ + gst_rtsp_connection_free (conn); + stop_server (); + iterate (); +} + +GST_END_TEST; + +static void +receive_rtp (GSocket * socket, GSocketAddress ** addr) +{ + GstBuffer *buffer = gst_buffer_new_allocate (NULL, 65536, NULL); + + for (;;) { + gssize bytes; + GstMapInfo map = GST_MAP_INFO_INIT; + GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT; + + gst_buffer_map (buffer, &map, GST_MAP_WRITE); + bytes = g_socket_receive_from (socket, addr, (gchar *) map.data, + map.maxsize, NULL, NULL); + fail_unless (bytes > 0); + gst_buffer_unmap (buffer, &map); + gst_buffer_set_size (buffer, bytes); + + if (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtpbuffer)) { + gst_rtp_buffer_unmap (&rtpbuffer); + break; + } + + if (addr) + g_clear_object (addr); + } + + gst_buffer_unref (buffer); +} + +static void +receive_rtcp (GSocket * socket, GSocketAddress ** addr, GstRTCPType type) +{ + GstBuffer *buffer = gst_buffer_new_allocate (NULL, 65536, NULL); + + for (;;) { + gssize bytes; + GstMapInfo map = GST_MAP_INFO_INIT; + + gst_buffer_map (buffer, &map, GST_MAP_WRITE); + bytes = g_socket_receive_from (socket, addr, (gchar *) map.data, + map.maxsize, NULL, NULL); + fail_unless (bytes > 0); + gst_buffer_unmap (buffer, &map); + gst_buffer_set_size (buffer, bytes); + + if (gst_rtcp_buffer_validate (buffer)) { + GstRTCPBuffer rtcpbuffer = GST_RTCP_BUFFER_INIT; + GstRTCPPacket packet; + + if (type) { + fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcpbuffer)); + fail_unless (gst_rtcp_buffer_get_first_packet (&rtcpbuffer, &packet)); + do { + if (gst_rtcp_packet_get_type (&packet) == type) { + gst_rtcp_buffer_unmap (&rtcpbuffer); + goto done; + } + } while (gst_rtcp_packet_move_to_next (&packet)); + gst_rtcp_buffer_unmap (&rtcpbuffer); + } else { + break; + } + } + + if (addr) + g_clear_object (addr); + } + +done: + + gst_buffer_unref (buffer); +} + +static void +do_test_play (const gchar * range) +{ + GstRTSPConnection *conn; + GstSDPMessage *sdp_message = NULL; + const GstSDPMedia *sdp_media; + const gchar *video_control; + const gchar *audio_control; + GstRTSPRange client_port; + gchar *session = NULL; + GstRTSPTransport *video_transport = NULL; + GstRTSPTransport *audio_transport = NULL; + GSocket *rtp_socket, *rtcp_socket; + gchar *range_out = NULL; + + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + sdp_message = do_describe (conn, TEST_MOUNT_POINT); + + /* get control strings from DESCRIBE response */ + fail_unless (gst_sdp_message_medias_len (sdp_message) == 2); + sdp_media = gst_sdp_message_get_media (sdp_message, 0); + video_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + sdp_media = gst_sdp_message_get_media (sdp_message, 1); + audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + + get_client_ports_full (&client_port, &rtp_socket, &rtcp_socket); + + /* do SETUP for video and audio */ + fail_unless (do_setup (conn, video_control, &client_port, &session, + &video_transport) == GST_RTSP_STS_OK); + fail_unless (do_setup (conn, audio_control, &client_port, &session, + &audio_transport) == GST_RTSP_STS_OK); + + /* send PLAY request and check that we get 200 OK */ + fail_unless (do_request (conn, GST_RTSP_PLAY, NULL, session, NULL, range, + NULL, NULL, NULL, NULL, NULL, &range_out) == GST_RTSP_STS_OK); + if (range) + fail_unless_equals_string (range, range_out); + g_free (range_out); + + receive_rtp (rtp_socket, NULL); + receive_rtcp (rtcp_socket, NULL, 0); + + /* send TEARDOWN request and check that we get 200 OK */ + fail_unless (do_simple_request (conn, GST_RTSP_TEARDOWN, + session) == GST_RTSP_STS_OK); + + /* FIXME: The rtsp-server always disconnects the transport before + * sending the RTCP BYE + * receive_rtcp (rtcp_socket, NULL, GST_RTCP_TYPE_BYE); + */ + + /* clean up and iterate so the clean-up can finish */ + g_object_unref (rtp_socket); + g_object_unref (rtcp_socket); + g_free (session); + gst_rtsp_transport_free (video_transport); + gst_rtsp_transport_free (audio_transport); + gst_sdp_message_free (sdp_message); + gst_rtsp_connection_free (conn); +} + + +GST_START_TEST (test_play) +{ + start_server (); + + do_test_play (NULL); + + stop_server (); + iterate (); +} + +GST_END_TEST; + +GST_START_TEST (test_play_without_session) +{ + GstRTSPConnection *conn; + + start_server (); + + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + /* send PLAY request without a session and check that we get a + * 454 Session Not Found */ + fail_unless (do_simple_request (conn, GST_RTSP_PLAY, + NULL) == GST_RTSP_STS_SESSION_NOT_FOUND); + + /* clean up and iterate so the clean-up can finish */ + gst_rtsp_connection_free (conn); + stop_server (); + iterate (); +} + +GST_END_TEST; + +GST_START_TEST (test_bind_already_in_use) +{ + GstRTSPServer *serv; + GSocketService *service; + GError *error = NULL; + guint16 port; + gchar *port_str; + + serv = gst_rtsp_server_new (); + service = g_socket_service_new (); + + /* bind service to port */ + port = + g_socket_listener_add_any_inet_port (G_SOCKET_LISTENER (service), NULL, + &error); + g_assert_no_error (error); + + port_str = g_strdup_printf ("%d\n", port); + + /* try to bind server to the same port */ + g_object_set (serv, "service", port_str, NULL); + g_free (port_str); + + /* attach to default main context */ + fail_unless (gst_rtsp_server_attach (serv, NULL) == 0); + + /* cleanup */ + g_object_unref (serv); + g_socket_service_stop (service); + g_object_unref (service); +} + +GST_END_TEST; + + +GST_START_TEST (test_play_multithreaded) +{ + GstRTSPThreadPool *pool; + + pool = gst_rtsp_server_get_thread_pool (server); + gst_rtsp_thread_pool_set_max_threads (pool, 2); + g_object_unref (pool); + + start_server (); + + do_test_play (NULL); + + stop_server (); + iterate (); +} + +GST_END_TEST; + +enum +{ + BLOCK_ME, + BLOCKED, + UNBLOCK +}; + + +static void +media_constructed_block (GstRTSPMediaFactory * factory, + GstRTSPMedia * media, gpointer user_data) +{ + gint *block_state = user_data; + + g_mutex_lock (&check_mutex); + + *block_state = BLOCKED; + g_cond_broadcast (&check_cond); + + while (*block_state != UNBLOCK) + g_cond_wait (&check_cond, &check_mutex); + g_mutex_unlock (&check_mutex); +} + + +GST_START_TEST (test_play_multithreaded_block_in_describe) +{ + GstRTSPConnection *conn; + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + gint block_state = BLOCK_ME; + GstRTSPMessage *request; + GstRTSPMessage *response; + GstRTSPStatusCode code; + GstRTSPThreadPool *pool; + + pool = gst_rtsp_server_get_thread_pool (server); + gst_rtsp_thread_pool_set_max_threads (pool, 2); + g_object_unref (pool); + + mounts = gst_rtsp_server_get_mount_points (server); + fail_unless (mounts != NULL); + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_launch (factory, + "( " VIDEO_PIPELINE " " AUDIO_PIPELINE " )"); + g_signal_connect (factory, "media-constructed", + G_CALLBACK (media_constructed_block), &block_state); + gst_rtsp_mount_points_add_factory (mounts, TEST_MOUNT_POINT "2", factory); + g_object_unref (mounts); + + start_server (); + + conn = connect_to_server (test_port, TEST_MOUNT_POINT "2"); + iterate (); + + /* do describe, it will not return now as we've blocked it */ + request = create_request (conn, GST_RTSP_DESCRIBE, NULL); + fail_unless (send_request (conn, request)); + gst_rtsp_message_free (request); + + g_mutex_lock (&check_mutex); + while (block_state != BLOCKED) + g_cond_wait (&check_cond, &check_mutex); + g_mutex_unlock (&check_mutex); + + /* Do a second connection while the first one is blocked */ + do_test_play (NULL); + + /* Now unblock the describe */ + g_mutex_lock (&check_mutex); + block_state = UNBLOCK; + g_cond_broadcast (&check_cond); + g_mutex_unlock (&check_mutex); + + response = read_response (conn); + gst_rtsp_message_parse_response (response, &code, NULL, NULL); + fail_unless (code == GST_RTSP_STS_OK); + gst_rtsp_message_free (response); + + + gst_rtsp_connection_free (conn); + stop_server (); + iterate (); + +} + +GST_END_TEST; + + +static void +new_session_timeout_one (GstRTSPClient * client, + GstRTSPSession * session, gpointer user_data) +{ + gst_rtsp_session_set_timeout (session, 1); + + g_signal_handlers_disconnect_by_func (client, new_session_timeout_one, + user_data); +} + +static void +session_connected_new_session_cb (GstRTSPServer * server, + GstRTSPClient * client, gpointer user_data) +{ + + g_signal_connect (client, "new-session", user_data, NULL); +} + +GST_START_TEST (test_play_multithreaded_timeout_client) +{ + GstRTSPConnection *conn; + GstSDPMessage *sdp_message = NULL; + const GstSDPMedia *sdp_media; + const gchar *video_control; + const gchar *audio_control; + GstRTSPRange client_port; + gchar *session = NULL; + GstRTSPTransport *video_transport = NULL; + GstRTSPTransport *audio_transport = NULL; + GstRTSPSessionPool *pool; + GstRTSPThreadPool *thread_pool; + + thread_pool = gst_rtsp_server_get_thread_pool (server); + gst_rtsp_thread_pool_set_max_threads (thread_pool, 2); + g_object_unref (thread_pool); + + pool = gst_rtsp_server_get_session_pool (server); + g_signal_connect (server, "client-connected", + G_CALLBACK (session_connected_new_session_cb), new_session_timeout_one); + + start_server (); + + + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + sdp_message = do_describe (conn, TEST_MOUNT_POINT); + + /* get control strings from DESCRIBE response */ + fail_unless (gst_sdp_message_medias_len (sdp_message) == 2); + sdp_media = gst_sdp_message_get_media (sdp_message, 0); + video_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + sdp_media = gst_sdp_message_get_media (sdp_message, 1); + audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + + get_client_ports (&client_port); + + /* do SETUP for video and audio */ + fail_unless (do_setup (conn, video_control, &client_port, &session, + &video_transport) == GST_RTSP_STS_OK); + fail_unless (do_setup (conn, audio_control, &client_port, &session, + &audio_transport) == GST_RTSP_STS_OK); + + fail_unless (gst_rtsp_session_pool_get_n_sessions (pool) == 1); + + /* send PLAY request and check that we get 200 OK */ + fail_unless (do_simple_request (conn, GST_RTSP_PLAY, + session) == GST_RTSP_STS_OK); + + sleep (7); + + fail_unless (gst_rtsp_session_pool_cleanup (pool) == 1); + fail_unless (gst_rtsp_session_pool_get_n_sessions (pool) == 0); + + /* clean up and iterate so the clean-up can finish */ + g_object_unref (pool); + g_free (session); + gst_rtsp_transport_free (video_transport); + gst_rtsp_transport_free (audio_transport); + gst_sdp_message_free (sdp_message); + gst_rtsp_connection_free (conn); + + stop_server (); + iterate (); +} + +GST_END_TEST; + + +GST_START_TEST (test_play_multithreaded_timeout_session) +{ + GstRTSPConnection *conn; + GstSDPMessage *sdp_message = NULL; + const GstSDPMedia *sdp_media; + const gchar *video_control; + const gchar *audio_control; + GstRTSPRange client_port; + gchar *session1 = NULL; + gchar *session2 = NULL; + GstRTSPTransport *video_transport = NULL; + GstRTSPTransport *audio_transport = NULL; + GstRTSPSessionPool *pool; + GstRTSPThreadPool *thread_pool; + + thread_pool = gst_rtsp_server_get_thread_pool (server); + gst_rtsp_thread_pool_set_max_threads (thread_pool, 2); + g_object_unref (thread_pool); + + pool = gst_rtsp_server_get_session_pool (server); + g_signal_connect (server, "client-connected", + G_CALLBACK (session_connected_new_session_cb), new_session_timeout_one); + + start_server (); + + + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + gst_rtsp_connection_set_remember_session_id (conn, FALSE); + + sdp_message = do_describe (conn, TEST_MOUNT_POINT); + + /* get control strings from DESCRIBE response */ + fail_unless (gst_sdp_message_medias_len (sdp_message) == 2); + sdp_media = gst_sdp_message_get_media (sdp_message, 0); + video_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + sdp_media = gst_sdp_message_get_media (sdp_message, 1); + audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + + get_client_ports (&client_port); + + /* do SETUP for video and audio */ + fail_unless (do_setup (conn, video_control, &client_port, &session1, + &video_transport) == GST_RTSP_STS_OK); + fail_unless (do_setup (conn, audio_control, &client_port, &session2, + &audio_transport) == GST_RTSP_STS_OK); + + fail_unless (gst_rtsp_session_pool_get_n_sessions (pool) == 2); + + /* send PLAY request and check that we get 200 OK */ + fail_unless (do_simple_request (conn, GST_RTSP_PLAY, + session1) == GST_RTSP_STS_OK); + fail_unless (do_simple_request (conn, GST_RTSP_PLAY, + session2) == GST_RTSP_STS_OK); + + sleep (7); + + fail_unless (gst_rtsp_session_pool_cleanup (pool) == 1); + + /* send TEARDOWN request and check that we get 454 Session Not found */ + fail_unless (do_simple_request (conn, GST_RTSP_TEARDOWN, + session1) == GST_RTSP_STS_SESSION_NOT_FOUND); + + fail_unless (do_simple_request (conn, GST_RTSP_TEARDOWN, + session2) == GST_RTSP_STS_OK); + + /* clean up and iterate so the clean-up can finish */ + g_object_unref (pool); + g_free (session1); + g_free (session2); + gst_rtsp_transport_free (video_transport); + gst_rtsp_transport_free (audio_transport); + gst_sdp_message_free (sdp_message); + gst_rtsp_connection_free (conn); + + stop_server (); + iterate (); +} + +GST_END_TEST; + + +GST_START_TEST (test_play_disconnect) +{ + GstRTSPConnection *conn; + GstSDPMessage *sdp_message = NULL; + const GstSDPMedia *sdp_media; + const gchar *video_control; + const gchar *audio_control; + GstRTSPRange client_port; + gchar *session = NULL; + GstRTSPTransport *video_transport = NULL; + GstRTSPTransport *audio_transport = NULL; + GstRTSPSessionPool *pool; + + pool = gst_rtsp_server_get_session_pool (server); + g_signal_connect (server, "client-connected", + G_CALLBACK (session_connected_new_session_cb), new_session_timeout_one); + + start_server (); + + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + sdp_message = do_describe (conn, TEST_MOUNT_POINT); + + /* get control strings from DESCRIBE response */ + fail_unless (gst_sdp_message_medias_len (sdp_message) == 2); + sdp_media = gst_sdp_message_get_media (sdp_message, 0); + video_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + sdp_media = gst_sdp_message_get_media (sdp_message, 1); + audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + + get_client_ports (&client_port); + + /* do SETUP for video and audio */ + fail_unless (do_setup (conn, video_control, &client_port, &session, + &video_transport) == GST_RTSP_STS_OK); + fail_unless (do_setup (conn, audio_control, &client_port, &session, + &audio_transport) == GST_RTSP_STS_OK); + + fail_unless (gst_rtsp_session_pool_get_n_sessions (pool) == 1); + + /* send PLAY request and check that we get 200 OK */ + fail_unless (do_simple_request (conn, GST_RTSP_PLAY, + session) == GST_RTSP_STS_OK); + + gst_rtsp_connection_free (conn); + + sleep (7); + + fail_unless (gst_rtsp_session_pool_get_n_sessions (pool) == 1); + fail_unless (gst_rtsp_session_pool_cleanup (pool) == 1); + + + /* clean up and iterate so the clean-up can finish */ + g_object_unref (pool); + g_free (session); + gst_rtsp_transport_free (video_transport); + gst_rtsp_transport_free (audio_transport); + gst_sdp_message_free (sdp_message); + + stop_server (); + iterate (); +} + +GST_END_TEST; + +/* Only different with test_play is the specific ports selected */ + +GST_START_TEST (test_play_specific_server_port) +{ + GstRTSPMountPoints *mounts; + gchar *service; + GstRTSPMediaFactory *factory; + GstRTSPAddressPool *pool; + GstRTSPConnection *conn; + GstSDPMessage *sdp_message = NULL; + const GstSDPMedia *sdp_media; + const gchar *video_control; + GstRTSPRange client_port; + gchar *session = NULL; + GstRTSPTransport *video_transport = NULL; + GSocket *rtp_socket, *rtcp_socket; + GSocketAddress *rtp_address, *rtcp_address; + guint16 rtp_port, rtcp_port; + + mounts = gst_rtsp_server_get_mount_points (server); + + factory = gst_rtsp_media_factory_new (); + pool = gst_rtsp_address_pool_new (); + gst_rtsp_address_pool_add_range (pool, GST_RTSP_ADDRESS_POOL_ANY_IPV4, + GST_RTSP_ADDRESS_POOL_ANY_IPV4, 7770, 7780, 0); + gst_rtsp_media_factory_set_address_pool (factory, pool); + g_object_unref (pool); + gst_rtsp_media_factory_set_launch (factory, "( " VIDEO_PIPELINE " )"); + gst_rtsp_mount_points_add_factory (mounts, TEST_MOUNT_POINT, factory); + g_object_unref (mounts); + + /* set port to any */ + gst_rtsp_server_set_service (server, "0"); + + /* attach to default main context */ + source_id = gst_rtsp_server_attach (server, NULL); + fail_if (source_id == 0); + + /* get port */ + service = gst_rtsp_server_get_service (server); + test_port = atoi (service); + fail_unless (test_port != 0); + g_free (service); + + GST_DEBUG ("rtsp server listening on port %d", test_port); + + + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + sdp_message = do_describe (conn, TEST_MOUNT_POINT); + + /* get control strings from DESCRIBE response */ + fail_unless (gst_sdp_message_medias_len (sdp_message) == 1); + sdp_media = gst_sdp_message_get_media (sdp_message, 0); + video_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + + get_client_ports_full (&client_port, &rtp_socket, &rtcp_socket); + + /* do SETUP for video */ + fail_unless (do_setup (conn, video_control, &client_port, &session, + &video_transport) == GST_RTSP_STS_OK); + + /* send PLAY request and check that we get 200 OK */ + fail_unless (do_simple_request (conn, GST_RTSP_PLAY, + session) == GST_RTSP_STS_OK); + + receive_rtp (rtp_socket, &rtp_address); + receive_rtcp (rtcp_socket, &rtcp_address, 0); + + fail_unless (G_IS_INET_SOCKET_ADDRESS (rtp_address)); + fail_unless (G_IS_INET_SOCKET_ADDRESS (rtcp_address)); + rtp_port = + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (rtp_address)); + rtcp_port = + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (rtcp_address)); + fail_unless (rtp_port >= 7770 && rtp_port <= 7780 && rtp_port % 2 == 0); + fail_unless (rtcp_port >= 7770 && rtcp_port <= 7780 && rtcp_port % 2 == 1); + fail_unless (rtp_port + 1 == rtcp_port); + + g_object_unref (rtp_address); + g_object_unref (rtcp_address); + + /* send TEARDOWN request and check that we get 200 OK */ + fail_unless (do_simple_request (conn, GST_RTSP_TEARDOWN, + session) == GST_RTSP_STS_OK); + + /* FIXME: The rtsp-server always disconnects the transport before + * sending the RTCP BYE + * receive_rtcp (rtcp_socket, NULL, GST_RTCP_TYPE_BYE); + */ + + /* clean up and iterate so the clean-up can finish */ + g_object_unref (rtp_socket); + g_object_unref (rtcp_socket); + g_free (session); + gst_rtsp_transport_free (video_transport); + gst_sdp_message_free (sdp_message); + gst_rtsp_connection_free (conn); + + + stop_server (); + iterate (); +} + +GST_END_TEST; + + +GST_START_TEST (test_play_smpte_range) +{ + start_server (); + + do_test_play ("npt=5-"); + do_test_play ("smpte=0:00:00-"); + do_test_play ("smpte=1:00:00-"); + do_test_play ("smpte=1:00:03-"); + do_test_play ("clock=20120321T152256Z-"); + + stop_server (); + iterate (); +} + +GST_END_TEST; + + +static Suite * +rtspserver_suite (void) +{ + Suite *s = suite_create ("rtspserver"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_add_checked_fixture (tc, setup, teardown); + tcase_set_timeout (tc, 20); + tcase_add_test (tc, test_connect); + tcase_add_test (tc, test_describe); + tcase_add_test (tc, test_describe_non_existing_mount_point); + tcase_add_test (tc, test_setup); + tcase_add_test (tc, test_setup_with_require_header); + tcase_add_test (tc, test_setup_non_existing_stream); + tcase_add_test (tc, test_play); + tcase_add_test (tc, test_play_without_session); + tcase_add_test (tc, test_bind_already_in_use); + tcase_add_test (tc, test_play_multithreaded); + tcase_add_test (tc, test_play_multithreaded_block_in_describe); + tcase_add_test (tc, test_play_multithreaded_timeout_client); + tcase_add_test (tc, test_play_multithreaded_timeout_session); + tcase_add_test (tc, test_play_disconnect); + tcase_add_test (tc, test_play_specific_server_port); + tcase_add_test (tc, test_play_smpte_range); + return s; +} + +GST_CHECK_MAIN (rtspserver); diff --git a/tests/check/gst/sessionmedia.c b/tests/check/gst/sessionmedia.c new file mode 100644 index 0000000..13445b4 --- /dev/null +++ b/tests/check/gst/sessionmedia.c @@ -0,0 +1,399 @@ +/* GStreamer + * Copyright (C) 2013 Branko Subasic + * + * 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. + */ + +#include + +#include +#include + +#define TEST_PATH "rtsp://localhost:8554/test" +#define SETUP_URL1 TEST_PATH "/stream=0" +#define SETUP_URL2 TEST_PATH "/stream=1" + +GST_START_TEST (test_setup_url) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url, *setup_url; + GstRTSPStream *stream; + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + GstRTSPSessionMedia *sm; + GstRTSPStreamTransport *trans; + GstRTSPTransport *ct; + gint match_len; + gchar *url_str, *url_str2; + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + fail_unless (gst_rtsp_url_parse (TEST_PATH, &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + fail_unless (gst_rtsp_media_n_streams (media) == 1); + + stream = gst_rtsp_media_get_stream (media, 0); + fail_unless (GST_IS_RTSP_STREAM (stream)); + + pool = gst_rtsp_thread_pool_new (); + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + + fail_unless (gst_rtsp_media_prepare (media, thread)); + + /* create session media and make sure it matches test path + * note that gst_rtsp_session_media_new takes ownership of the media + * thus no need to unref it at the bottom of function */ + sm = gst_rtsp_session_media_new (TEST_PATH, media); + fail_unless (GST_IS_RTSP_SESSION_MEDIA (sm)); + fail_unless (gst_rtsp_session_media_matches (sm, TEST_PATH, &match_len)); + fail_unless (match_len == strlen (TEST_PATH)); + fail_unless (gst_rtsp_session_media_get_media (sm) == media); + + /* make a transport for the stream */ + gst_rtsp_transport_new (&ct); + trans = gst_rtsp_session_media_set_transport (sm, stream, ct); + fail_unless (gst_rtsp_session_media_get_transport (sm, 0) == trans); + + /* make sure there's no setup url stored initially */ + fail_unless (gst_rtsp_stream_transport_get_url (trans) == NULL); + + /* now store a setup url and make sure it can be retrieved and that it's correct */ + fail_unless (gst_rtsp_url_parse (SETUP_URL1, &setup_url) == GST_RTSP_OK); + gst_rtsp_stream_transport_set_url (trans, setup_url); + + url_str = gst_rtsp_url_get_request_uri (setup_url); + url_str2 = + gst_rtsp_url_get_request_uri (gst_rtsp_stream_transport_get_url (trans)); + fail_if (g_strcmp0 (url_str, url_str2) != 0); + g_free (url_str); + g_free (url_str2); + + /* check that it's ok to try to store the same url again */ + gst_rtsp_stream_transport_set_url (trans, setup_url); + + fail_unless (gst_rtsp_media_unprepare (media)); + + gst_rtsp_url_free (setup_url); + gst_rtsp_url_free (url); + + g_object_unref (sm); + + g_object_unref (factory); + g_object_unref (pool); +} + +GST_END_TEST; + +GST_START_TEST (test_rtsp_state) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url; + GstRTSPStream *stream; + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + GstRTSPSessionMedia *sm; + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + fail_unless (gst_rtsp_url_parse (TEST_PATH, &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + fail_unless (gst_rtsp_media_n_streams (media) == 1); + + stream = gst_rtsp_media_get_stream (media, 0); + fail_unless (GST_IS_RTSP_STREAM (stream)); + + pool = gst_rtsp_thread_pool_new (); + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + + fail_unless (gst_rtsp_media_prepare (media, thread)); + + sm = gst_rtsp_session_media_new (TEST_PATH, media); + fail_unless (GST_IS_RTSP_SESSION_MEDIA (sm)); + fail_unless_equals_int (gst_rtsp_session_media_get_rtsp_state (sm), + GST_RTSP_STATE_INIT); + + gst_rtsp_session_media_set_rtsp_state (sm, GST_RTSP_STATE_READY); + fail_unless_equals_int (gst_rtsp_session_media_get_rtsp_state (sm), + GST_RTSP_STATE_READY); + + gst_rtsp_session_media_set_rtsp_state (sm, GST_RTSP_STATE_SEEKING); + fail_unless_equals_int (gst_rtsp_session_media_get_rtsp_state (sm), + GST_RTSP_STATE_SEEKING); + + gst_rtsp_session_media_set_rtsp_state (sm, GST_RTSP_STATE_PLAYING); + fail_unless_equals_int (gst_rtsp_session_media_get_rtsp_state (sm), + GST_RTSP_STATE_PLAYING); + + gst_rtsp_session_media_set_rtsp_state (sm, GST_RTSP_STATE_RECORDING); + fail_unless_equals_int (gst_rtsp_session_media_get_rtsp_state (sm), + GST_RTSP_STATE_RECORDING); + + fail_unless (gst_rtsp_media_unprepare (media)); + + gst_rtsp_url_free (url); + + g_object_unref (sm); + + g_object_unref (factory); + g_object_unref (pool); +} + +GST_END_TEST; + +GST_START_TEST (test_transports) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url; + GstRTSPStream *stream1, *stream2; + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + GstRTSPSessionMedia *sm; + GstRTSPStreamTransport *trans; + GstRTSPTransport *ct1, *ct2, *ct3, *ct4; + gint match_len; + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + fail_unless (gst_rtsp_url_parse (TEST_PATH, &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 audiotestsrc ! rtpgstpay pt=97 name=pay1 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + fail_unless (gst_rtsp_media_n_streams (media) == 2); + + stream1 = gst_rtsp_media_get_stream (media, 0); + fail_unless (GST_IS_RTSP_STREAM (stream1)); + + stream2 = gst_rtsp_media_get_stream (media, 1); + fail_unless (GST_IS_RTSP_STREAM (stream2)); + + pool = gst_rtsp_thread_pool_new (); + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + + fail_unless (gst_rtsp_media_prepare (media, thread)); + + sm = gst_rtsp_session_media_new (TEST_PATH, media); + fail_unless (GST_IS_RTSP_SESSION_MEDIA (sm)); + fail_unless (gst_rtsp_session_media_matches (sm, TEST_PATH, &match_len)); + fail_unless (match_len == strlen (TEST_PATH)); + + gst_rtsp_transport_new (&ct1); + trans = gst_rtsp_session_media_set_transport (sm, stream1, ct1); + fail_unless (gst_rtsp_session_media_get_transport (sm, 0) == trans); + + gst_rtsp_transport_new (&ct2); + trans = gst_rtsp_session_media_set_transport (sm, stream1, ct2); + fail_unless (gst_rtsp_session_media_get_transport (sm, 0) == trans); + + gst_rtsp_transport_new (&ct3); + trans = gst_rtsp_session_media_set_transport (sm, stream2, ct3); + fail_unless (gst_rtsp_session_media_get_transport (sm, 1) == trans); + + gst_rtsp_transport_new (&ct4); + trans = gst_rtsp_session_media_set_transport (sm, stream2, ct4); + fail_unless (gst_rtsp_session_media_get_transport (sm, 1) == trans); + + fail_unless (gst_rtsp_media_unprepare (media)); + + gst_rtsp_url_free (url); + + g_object_unref (sm); + + g_object_unref (factory); + g_object_unref (pool); +} + +GST_END_TEST; + +GST_START_TEST (test_time_and_rtpinfo) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url; + GstRTSPStream *stream1, *stream2; + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + GstRTSPSessionMedia *sm; + GstClockTime base_time; + gchar *rtpinfo; + GstRTSPTransport *ct1; + GstRTSPStreamTransport *trans; + GstRTSPUrl *setup_url; + gchar **streaminfo; + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + fail_unless (gst_rtsp_url_parse (TEST_PATH, &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc do-timestamp=true timestamp-offset=0 ! rtpvrawpay pt=96 name=pay0 " + "audiotestsrc do-timestamp=true timestamp-offset=1000000000 ! rtpgstpay pt=97 name=pay1 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + fail_unless (gst_rtsp_media_n_streams (media) == 2); + + stream1 = gst_rtsp_media_get_stream (media, 0); + fail_unless (GST_IS_RTSP_STREAM (stream1)); + + stream2 = gst_rtsp_media_get_stream (media, 1); + fail_unless (GST_IS_RTSP_STREAM (stream2)); + + pool = gst_rtsp_thread_pool_new (); + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + + fail_unless (gst_rtsp_media_prepare (media, thread)); + + sm = gst_rtsp_session_media_new (TEST_PATH, media); + fail_unless (GST_IS_RTSP_SESSION_MEDIA (sm)); + + base_time = gst_rtsp_session_media_get_base_time (sm); + fail_unless_equals_int64 (base_time, 0); + + rtpinfo = gst_rtsp_session_media_get_rtpinfo (sm); + fail_unless (rtpinfo == NULL); + + gst_rtsp_transport_new (&ct1); + trans = gst_rtsp_session_media_set_transport (sm, stream1, ct1); + fail_unless (gst_rtsp_session_media_get_transport (sm, 0) == trans); + fail_unless (gst_rtsp_url_parse (SETUP_URL1, &setup_url) == GST_RTSP_OK); + gst_rtsp_stream_transport_set_url (trans, setup_url); + + base_time = gst_rtsp_session_media_get_base_time (sm); + fail_unless_equals_int64 (base_time, 0); + + rtpinfo = gst_rtsp_session_media_get_rtpinfo (sm); + streaminfo = g_strsplit (rtpinfo, ",", 1); + g_free (rtpinfo); + + fail_unless (g_strstr_len (streaminfo[0], -1, "url=") != NULL); + fail_unless (g_strstr_len (streaminfo[0], -1, "seq=") != NULL); + fail_unless (g_strstr_len (streaminfo[0], -1, "rtptime=") != NULL); + fail_unless (g_strstr_len (streaminfo[0], -1, SETUP_URL1) != NULL); + + g_strfreev (streaminfo); + + fail_unless (gst_rtsp_media_unprepare (media)); + + rtpinfo = gst_rtsp_session_media_get_rtpinfo (sm); + fail_unless (rtpinfo == NULL); + + gst_rtsp_url_free (setup_url); + gst_rtsp_url_free (url); + + g_object_unref (sm); + + g_object_unref (factory); + g_object_unref (pool); +} + +GST_END_TEST; + +GST_START_TEST (test_allocate_channels) +{ + GstRTSPMediaFactory *factory; + GstRTSPMedia *media; + GstRTSPUrl *url; + GstRTSPStream *stream; + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + GstRTSPSessionMedia *sm; + GstRTSPRange range; + + factory = gst_rtsp_media_factory_new (); + fail_if (gst_rtsp_media_factory_is_shared (factory)); + fail_unless (gst_rtsp_url_parse (TEST_PATH, &url) == GST_RTSP_OK); + + gst_rtsp_media_factory_set_launch (factory, + "( videotestsrc ! rtpvrawpay pt=96 name=pay0 )"); + + media = gst_rtsp_media_factory_construct (factory, url); + fail_unless (GST_IS_RTSP_MEDIA (media)); + + fail_unless (gst_rtsp_media_n_streams (media) == 1); + + stream = gst_rtsp_media_get_stream (media, 0); + fail_unless (GST_IS_RTSP_STREAM (stream)); + + pool = gst_rtsp_thread_pool_new (); + thread = gst_rtsp_thread_pool_get_thread (pool, + GST_RTSP_THREAD_TYPE_MEDIA, NULL); + + fail_unless (gst_rtsp_media_prepare (media, thread)); + + sm = gst_rtsp_session_media_new (TEST_PATH, media); + fail_unless (GST_IS_RTSP_SESSION_MEDIA (sm)); + + fail_unless (gst_rtsp_session_media_alloc_channels (sm, &range)); + fail_unless_equals_int (range.min, 0); + fail_unless_equals_int (range.max, 1); + + fail_unless (gst_rtsp_session_media_alloc_channels (sm, &range)); + fail_unless_equals_int (range.min, 2); + fail_unless_equals_int (range.max, 3); + + fail_unless (gst_rtsp_media_unprepare (media)); + + gst_rtsp_url_free (url); + + g_object_unref (sm); + + g_object_unref (factory); + g_object_unref (pool); +} + +GST_END_TEST; +static Suite * +rtspsessionmedia_suite (void) +{ + Suite *s = suite_create ("rtspsessionmedia"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_set_timeout (tc, 20); + tcase_add_test (tc, test_setup_url); + tcase_add_test (tc, test_rtsp_state); + tcase_add_test (tc, test_transports); + tcase_add_test (tc, test_time_and_rtpinfo); + tcase_add_test (tc, test_allocate_channels); + + return s; +} + +GST_CHECK_MAIN (rtspsessionmedia); diff --git a/tests/check/gst/sessionpool.c b/tests/check/gst/sessionpool.c new file mode 100644 index 0000000..c1cc149 --- /dev/null +++ b/tests/check/gst/sessionpool.c @@ -0,0 +1,197 @@ +/* GStreamer + * Copyright (C) 2014 Sebastian Rasmussen + * + * 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. + */ + +#include +#include + +typedef struct +{ + GstRTSPSession *sessions[3]; + GstRTSPFilterResult response[3]; +} Responses; + +static GstRTSPFilterResult +filter_func (GstRTSPSessionPool * pool, GstRTSPSession * session, + gpointer user_data) +{ + Responses *responses = (Responses *) user_data; + gint i; + + for (i = 0; i < 3; i++) + if (session == responses->sessions[i]) + return responses->response[i]; + + return GST_RTSP_FILTER_KEEP; +} + +GST_START_TEST (test_pool) +{ + GstRTSPSessionPool *pool; + GstRTSPSession *session1, *session2, *session3; + GstRTSPSession *compare; + gchar *session1id, *session2id, *session3id; + GList *list; + guint maxsessions; + GSource *source; + guint sourceid; + + pool = gst_rtsp_session_pool_new (); + fail_unless_equals_int (gst_rtsp_session_pool_get_n_sessions (pool), 0); + fail_unless_equals_int (gst_rtsp_session_pool_get_max_sessions (pool), 0); + + gst_rtsp_session_pool_set_max_sessions (pool, 3); + fail_unless_equals_int (gst_rtsp_session_pool_get_max_sessions (pool), 3); + + session1 = gst_rtsp_session_pool_create (pool); + fail_unless (GST_IS_RTSP_SESSION (session1)); + fail_unless_equals_int (gst_rtsp_session_pool_get_n_sessions (pool), 1); + fail_unless_equals_int (gst_rtsp_session_pool_get_max_sessions (pool), 3); + session1id = g_strdup (gst_rtsp_session_get_sessionid (session1)); + + session2 = gst_rtsp_session_pool_create (pool); + fail_unless (GST_IS_RTSP_SESSION (session2)); + fail_unless_equals_int (gst_rtsp_session_pool_get_n_sessions (pool), 2); + fail_unless_equals_int (gst_rtsp_session_pool_get_max_sessions (pool), 3); + session2id = g_strdup (gst_rtsp_session_get_sessionid (session2)); + + session3 = gst_rtsp_session_pool_create (pool); + fail_unless (GST_IS_RTSP_SESSION (session3)); + fail_unless_equals_int (gst_rtsp_session_pool_get_n_sessions (pool), 3); + fail_unless_equals_int (gst_rtsp_session_pool_get_max_sessions (pool), 3); + session3id = g_strdup (gst_rtsp_session_get_sessionid (session3)); + + fail_if (GST_IS_RTSP_SESSION (gst_rtsp_session_pool_create (pool))); + + compare = gst_rtsp_session_pool_find (pool, session1id); + fail_unless (compare == session1); + g_object_unref (compare); + compare = gst_rtsp_session_pool_find (pool, session2id); + fail_unless (compare == session2); + g_object_unref (compare); + compare = gst_rtsp_session_pool_find (pool, session3id); + fail_unless (compare == session3); + g_object_unref (compare); + fail_unless (gst_rtsp_session_pool_find (pool, "") == NULL); + + fail_unless (gst_rtsp_session_pool_remove (pool, session2)); + g_object_unref (session2); + fail_unless_equals_int (gst_rtsp_session_pool_get_n_sessions (pool), 2); + fail_unless_equals_int (gst_rtsp_session_pool_get_max_sessions (pool), 3); + + gst_rtsp_session_pool_set_max_sessions (pool, 2); + fail_unless_equals_int (gst_rtsp_session_pool_get_n_sessions (pool), 2); + fail_unless_equals_int (gst_rtsp_session_pool_get_max_sessions (pool), 2); + + session2 = gst_rtsp_session_pool_create (pool); + fail_if (GST_IS_RTSP_SESSION (session2)); + + { + list = gst_rtsp_session_pool_filter (pool, NULL, NULL); + fail_unless_equals_int (g_list_length (list), 2); + fail_unless (g_list_find (list, session1) != NULL); + fail_unless (g_list_find (list, session3) != NULL); + g_list_free_full (list, (GDestroyNotify) g_object_unref); + } + + { + Responses responses = { + {session1, session2, session3}, + {GST_RTSP_FILTER_KEEP, GST_RTSP_FILTER_KEEP, GST_RTSP_FILTER_KEEP}, + }; + + list = gst_rtsp_session_pool_filter (pool, filter_func, &responses); + fail_unless (list == NULL); + } + + { + Responses responses = { + {session1, session2, session3}, + {GST_RTSP_FILTER_REF, GST_RTSP_FILTER_KEEP, GST_RTSP_FILTER_KEEP}, + }; + + list = gst_rtsp_session_pool_filter (pool, filter_func, &responses); + fail_unless_equals_int (g_list_length (list), 1); + fail_unless (g_list_nth_data (list, 0) == session1); + g_list_free_full (list, (GDestroyNotify) g_object_unref); + } + + { + Responses responses = { + {session1, session2, session3}, + {GST_RTSP_FILTER_KEEP, GST_RTSP_FILTER_KEEP, GST_RTSP_FILTER_REMOVE}, + }; + + list = gst_rtsp_session_pool_filter (pool, filter_func, &responses); + fail_unless_equals_int (g_list_length (list), 0); + g_list_free (list); + } + + compare = gst_rtsp_session_pool_find (pool, session1id); + fail_unless (compare == session1); + g_object_unref (compare); + fail_unless (gst_rtsp_session_pool_find (pool, session2id) == NULL); + fail_unless (gst_rtsp_session_pool_find (pool, session3id) == NULL); + + g_object_get (pool, "max-sessions", &maxsessions, NULL); + fail_unless_equals_int (maxsessions, 2); + + g_object_set (pool, "max-sessions", 3, NULL); + g_object_get (pool, "max-sessions", &maxsessions, NULL); + fail_unless_equals_int (maxsessions, 3); + + fail_unless_equals_int (gst_rtsp_session_pool_cleanup (pool), 0); + + gst_rtsp_session_set_timeout (session1, 1); + + source = gst_rtsp_session_pool_create_watch (pool); + fail_unless (source != NULL); + + sourceid = g_source_attach (source, NULL); + fail_unless (sourceid != 0); + + while (!g_main_context_iteration (NULL, TRUE)); + + g_source_unref (source); + + g_object_unref (session1); + g_object_unref (session3); + + g_free (session1id); + g_free (session2id); + g_free (session3id); + + g_object_unref (pool); +} + +GST_END_TEST; + +static Suite * +rtspsessionpool_suite (void) +{ + Suite *s = suite_create ("rtspsessionpool"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_set_timeout (tc, 15); + tcase_add_test (tc, test_pool); + + return s; +} + +GST_CHECK_MAIN (rtspsessionpool); diff --git a/tests/check/gst/stream.c b/tests/check/gst/stream.c new file mode 100644 index 0000000..582e674 --- /dev/null +++ b/tests/check/gst/stream.c @@ -0,0 +1,172 @@ +/* GStreamer + * Copyright (C) 2013 Axis Communications AB + * + * 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. + */ + +#include + +#include +#include + +GST_START_TEST (test_get_sockets) +{ + GstPad *srcpad; + GstElement *pay; + GstRTSPStream *stream; + GstBin *bin; + GstElement *rtpbin; + GSocket *socket; + gboolean have_ipv4; + gboolean have_ipv6; + + srcpad = gst_pad_new ("testsrcpad", GST_PAD_SRC); + fail_unless (srcpad != NULL); + gst_pad_set_active (srcpad, TRUE); + pay = gst_element_factory_make ("rtpgstpay", "testpayloader"); + fail_unless (pay != NULL); + stream = gst_rtsp_stream_new (0, pay, srcpad); + fail_unless (stream != NULL); + gst_object_unref (pay); + gst_object_unref (srcpad); + rtpbin = gst_element_factory_make ("rtpbin", "testrtpbin"); + fail_unless (rtpbin != NULL); + bin = GST_BIN (gst_bin_new ("testbin")); + fail_unless (bin != NULL); + fail_unless (gst_bin_add (bin, rtpbin)); + + fail_unless (gst_rtsp_stream_join_bin (stream, bin, rtpbin, GST_STATE_NULL)); + + socket = gst_rtsp_stream_get_rtp_socket (stream, G_SOCKET_FAMILY_IPV4); + have_ipv4 = (socket != NULL); + if (have_ipv4) { + fail_unless (g_socket_get_fd (socket) >= 0); + g_object_unref (socket); + } + + socket = gst_rtsp_stream_get_rtcp_socket (stream, G_SOCKET_FAMILY_IPV4); + if (have_ipv4) { + fail_unless (socket != NULL); + fail_unless (g_socket_get_fd (socket) >= 0); + g_object_unref (socket); + } else { + fail_unless (socket == NULL); + } + + socket = gst_rtsp_stream_get_rtp_socket (stream, G_SOCKET_FAMILY_IPV6); + have_ipv6 = (socket != NULL); + if (have_ipv6) { + fail_unless (g_socket_get_fd (socket) >= 0); + g_object_unref (socket); + } + + socket = gst_rtsp_stream_get_rtcp_socket (stream, G_SOCKET_FAMILY_IPV6); + if (have_ipv6) { + fail_unless (socket != NULL); + fail_unless (g_socket_get_fd (socket) >= 0); + g_object_unref (socket); + } else { + fail_unless (socket == NULL); + } + + /* check that at least one family is available */ + fail_unless (have_ipv4 || have_ipv6); + + fail_unless (gst_rtsp_stream_leave_bin (stream, bin, rtpbin)); + + gst_object_unref (bin); + gst_object_unref (stream); +} + +GST_END_TEST; + +GST_START_TEST (test_get_multicast_address) +{ + GstPad *srcpad; + GstElement *pay; + GstRTSPStream *stream; + GstRTSPAddressPool *pool; + GstRTSPAddress *addr1; + GstRTSPAddress *addr2; + + srcpad = gst_pad_new ("testsrcpad", GST_PAD_SRC); + fail_unless (srcpad != NULL); + gst_pad_set_active (srcpad, TRUE); + pay = gst_element_factory_make ("rtpgstpay", "testpayloader"); + fail_unless (pay != NULL); + stream = gst_rtsp_stream_new (0, pay, srcpad); + fail_unless (stream != NULL); + gst_object_unref (pay); + gst_object_unref (srcpad); + + pool = gst_rtsp_address_pool_new (); + fail_unless (gst_rtsp_address_pool_add_range (pool, + "233.252.0.0", "233.252.0.0", 5000, 5001, 1)); + fail_unless (gst_rtsp_address_pool_add_range (pool, + "FF11:DB8::1", "FF11:DB8::1", 5002, 5003, 1)); + gst_rtsp_stream_set_address_pool (stream, pool); + + addr1 = gst_rtsp_stream_get_multicast_address (stream, G_SOCKET_FAMILY_IPV4); + fail_unless (addr1 != NULL); + fail_unless_equals_string (addr1->address, "233.252.0.0"); + fail_unless_equals_int (addr1->port, 5000); + fail_unless_equals_int (addr1->n_ports, 2); + + addr2 = gst_rtsp_stream_get_multicast_address (stream, G_SOCKET_FAMILY_IPV4); + fail_unless (addr2 != NULL); + fail_unless_equals_string (addr2->address, "233.252.0.0"); + fail_unless_equals_int (addr2->port, 5000); + fail_unless_equals_int (addr2->n_ports, 2); + + gst_rtsp_address_free (addr1); + gst_rtsp_address_free (addr2); + + addr1 = gst_rtsp_stream_get_multicast_address (stream, G_SOCKET_FAMILY_IPV6); + fail_unless (addr1 != NULL); + fail_unless (!g_ascii_strcasecmp (addr1->address, "FF11:DB8::1")); + fail_unless_equals_int (addr1->port, 5002); + fail_unless_equals_int (addr1->n_ports, 2); + + addr2 = gst_rtsp_stream_get_multicast_address (stream, G_SOCKET_FAMILY_IPV6); + fail_unless (addr2 != NULL); + fail_unless (!g_ascii_strcasecmp (addr2->address, "FF11:DB8::1")); + fail_unless_equals_int (addr2->port, 5002); + fail_unless_equals_int (addr2->n_ports, 2); + + gst_rtsp_address_free (addr1); + gst_rtsp_address_free (addr2); + + g_object_unref (pool); + + gst_object_unref (stream); +} + +GST_END_TEST; + +static Suite * +rtspstream_suite (void) +{ + Suite *s = suite_create ("rtspstream"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_add_test (tc, test_get_sockets); + tcase_add_test (tc, test_get_multicast_address); + + return s; +} + +GST_CHECK_MAIN (rtspstream); diff --git a/tests/check/gst/threadpool.c b/tests/check/gst/threadpool.c new file mode 100644 index 0000000..c92e64f --- /dev/null +++ b/tests/check/gst/threadpool.c @@ -0,0 +1,236 @@ +/* GStreamer + * unit tests for GstRTSPThreadPool + * Copyright (C) 2013 Axis Communications + * @author Ognyan Tonchev + * + * 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. + */ + +#include + +#include + +GST_START_TEST (test_pool_get_thread) +{ + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + + pool = gst_rtsp_thread_pool_new (); + fail_unless (GST_IS_RTSP_THREAD_POOL (pool)); + + thread = gst_rtsp_thread_pool_get_thread (pool, GST_RTSP_THREAD_TYPE_CLIENT, + NULL); + fail_unless (GST_IS_RTSP_THREAD (thread)); + /* one ref is hold by the pool */ + fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT (thread), 2); + + gst_rtsp_thread_stop (thread); + g_object_unref (pool); + gst_rtsp_thread_pool_cleanup (); +} + +GST_END_TEST; + +GST_START_TEST (test_pool_get_media_thread) +{ + GstRTSPThreadPool *pool; + GstRTSPThread *thread; + + pool = gst_rtsp_thread_pool_new (); + fail_unless (GST_IS_RTSP_THREAD_POOL (pool)); + + thread = gst_rtsp_thread_pool_get_thread (pool, GST_RTSP_THREAD_TYPE_MEDIA, + NULL); + fail_unless (GST_IS_RTSP_THREAD (thread)); + /* one ref is hold by the pool */ + fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT (thread), 2); + + gst_rtsp_thread_stop (thread); + g_object_unref (pool); + gst_rtsp_thread_pool_cleanup (); +} + +GST_END_TEST; + +GST_START_TEST (test_pool_get_thread_reuse) +{ + GstRTSPThreadPool *pool; + GstRTSPThread *thread1; + GstRTSPThread *thread2; + + pool = gst_rtsp_thread_pool_new (); + fail_unless (GST_IS_RTSP_THREAD_POOL (pool)); + + gst_rtsp_thread_pool_set_max_threads (pool, 1); + + thread1 = gst_rtsp_thread_pool_get_thread (pool, GST_RTSP_THREAD_TYPE_CLIENT, + NULL); + fail_unless (GST_IS_RTSP_THREAD (thread1)); + + thread2 = gst_rtsp_thread_pool_get_thread (pool, GST_RTSP_THREAD_TYPE_CLIENT, + NULL); + fail_unless (GST_IS_RTSP_THREAD (thread2)); + + fail_unless (thread2 == thread1); + /* one ref is hold by the pool */ + fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT (thread1), 3); + + gst_rtsp_thread_stop (thread1); + gst_rtsp_thread_stop (thread2); + g_object_unref (pool); + + gst_rtsp_thread_pool_cleanup (); +} + +GST_END_TEST; + +static void +do_test_pool_max_thread (gboolean use_property) +{ + GstRTSPThreadPool *pool; + GstRTSPThread *thread1; + GstRTSPThread *thread2; + GstRTSPThread *thread3; + gint max_threads; + + pool = gst_rtsp_thread_pool_new (); + fail_unless (GST_IS_RTSP_THREAD_POOL (pool)); + + if (use_property) { + g_object_get (pool, "max-threads", &max_threads, NULL); + fail_unless_equals_int (max_threads, 1); + } else { + fail_unless_equals_int (gst_rtsp_thread_pool_get_max_threads (pool), 1); + } + + thread1 = gst_rtsp_thread_pool_get_thread (pool, GST_RTSP_THREAD_TYPE_CLIENT, + NULL); + fail_unless (GST_IS_RTSP_THREAD (thread1)); + + thread2 = gst_rtsp_thread_pool_get_thread (pool, GST_RTSP_THREAD_TYPE_CLIENT, + NULL); + fail_unless (GST_IS_RTSP_THREAD (thread2)); + + fail_unless (thread1 == thread2); + + gst_rtsp_thread_stop (thread1); + gst_rtsp_thread_stop (thread2); + + if (use_property) { + g_object_set (pool, "max-threads", 2, NULL); + g_object_get (pool, "max-threads", &max_threads, NULL); + fail_unless_equals_int (max_threads, 2); + } else { + gst_rtsp_thread_pool_set_max_threads (pool, 2); + fail_unless_equals_int (gst_rtsp_thread_pool_get_max_threads (pool), 2); + } + + thread1 = gst_rtsp_thread_pool_get_thread (pool, GST_RTSP_THREAD_TYPE_CLIENT, + NULL); + fail_unless (GST_IS_RTSP_THREAD (thread1)); + + thread2 = gst_rtsp_thread_pool_get_thread (pool, GST_RTSP_THREAD_TYPE_CLIENT, + NULL); + fail_unless (GST_IS_RTSP_THREAD (thread2)); + + thread3 = gst_rtsp_thread_pool_get_thread (pool, GST_RTSP_THREAD_TYPE_CLIENT, + NULL); + fail_unless (GST_IS_RTSP_THREAD (thread3)); + + fail_unless (thread2 != thread1); + fail_unless (thread3 == thread2 || thread3 == thread1); + + gst_rtsp_thread_stop (thread1); + gst_rtsp_thread_stop (thread2); + gst_rtsp_thread_stop (thread3); + + if (use_property) { + g_object_set (pool, "max-threads", 0, NULL); + g_object_get (pool, "max-threads", &max_threads, NULL); + fail_unless_equals_int (max_threads, 0); + } else { + gst_rtsp_thread_pool_set_max_threads (pool, 0); + fail_unless_equals_int (gst_rtsp_thread_pool_get_max_threads (pool), 0); + } + + thread1 = gst_rtsp_thread_pool_get_thread (pool, GST_RTSP_THREAD_TYPE_CLIENT, + NULL); + fail_if (GST_IS_RTSP_THREAD (thread1)); + + g_object_unref (pool); + + gst_rtsp_thread_pool_cleanup (); +} + +GST_START_TEST (test_pool_max_threads) +{ + do_test_pool_max_thread (FALSE); +} + +GST_END_TEST; + +GST_START_TEST (test_pool_max_threads_property) +{ + do_test_pool_max_thread (TRUE); +} + +GST_END_TEST; + +GST_START_TEST (test_pool_thread_copy) +{ + GstRTSPThreadPool *pool; + GstRTSPThread *thread1; + GstRTSPThread *thread2; + + pool = gst_rtsp_thread_pool_new (); + fail_unless (GST_IS_RTSP_THREAD_POOL (pool)); + + thread1 = gst_rtsp_thread_pool_get_thread (pool, GST_RTSP_THREAD_TYPE_CLIENT, + NULL); + fail_unless (GST_IS_RTSP_THREAD (thread1)); + fail_unless (GST_IS_MINI_OBJECT_TYPE (thread1, GST_TYPE_RTSP_THREAD)); + + thread2 = GST_RTSP_THREAD (gst_mini_object_copy (GST_MINI_OBJECT (thread1))); + fail_unless (GST_IS_RTSP_THREAD (thread2)); + fail_unless (GST_IS_MINI_OBJECT_TYPE (thread2, GST_TYPE_RTSP_THREAD)); + + gst_rtsp_thread_stop (thread1); + gst_rtsp_thread_stop (thread2); + g_object_unref (pool); + gst_rtsp_thread_pool_cleanup (); +} + +GST_END_TEST; + +static Suite * +rtspthreadpool_suite (void) +{ + Suite *s = suite_create ("rtspthreadpool"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_set_timeout (tc, 20); + tcase_add_test (tc, test_pool_get_thread); + tcase_add_test (tc, test_pool_get_media_thread); + tcase_add_test (tc, test_pool_get_thread_reuse); + tcase_add_test (tc, test_pool_max_threads); + tcase_add_test (tc, test_pool_max_threads_property); + tcase_add_test (tc, test_pool_thread_copy); + + return s; +} + +GST_CHECK_MAIN (rtspthreadpool); diff --git a/tests/check/gst/token.c b/tests/check/gst/token.c new file mode 100644 index 0000000..df5bbd5 --- /dev/null +++ b/tests/check/gst/token.c @@ -0,0 +1,99 @@ +/* GStreamer + * Copyright (C) 2013 Sebastian Rasmussen + * + * 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. + */ + +#include + +#include + +GST_START_TEST (test_token) +{ + GstRTSPToken *token; + GstRTSPToken *token2; + GstRTSPToken *copy; + GstStructure *str; + + token = gst_rtsp_token_new_empty (); + fail_if (gst_rtsp_token_is_allowed (token, "missing")); + gst_rtsp_token_unref (token); + + token = gst_rtsp_token_new ("role", G_TYPE_STRING, "user", + "permission1", G_TYPE_BOOLEAN, TRUE, + "permission2", G_TYPE_BOOLEAN, FALSE, NULL); + fail_unless_equals_string (gst_rtsp_token_get_string (token, "role"), "user"); + fail_unless (gst_rtsp_token_is_allowed (token, "permission1")); + fail_if (gst_rtsp_token_is_allowed (token, "permission2")); + fail_if (gst_rtsp_token_is_allowed (token, "missing")); + copy = GST_RTSP_TOKEN (gst_mini_object_copy (GST_MINI_OBJECT (token))); + gst_rtsp_token_unref (token); + fail_unless_equals_string (gst_rtsp_token_get_string (copy, "role"), "user"); + fail_unless (gst_rtsp_token_is_allowed (copy, "permission1")); + fail_if (gst_rtsp_token_is_allowed (copy, "permission2")); + fail_if (gst_rtsp_token_is_allowed (copy, "missing")); + gst_rtsp_token_unref (copy); + + token = gst_rtsp_token_new ("role", G_TYPE_STRING, "user", + "permission1", G_TYPE_BOOLEAN, TRUE, + "permission2", G_TYPE_BOOLEAN, FALSE, NULL); + fail_unless_equals_string (gst_rtsp_token_get_string (token, "role"), "user"); + fail_unless (gst_rtsp_token_is_allowed (token, "permission1")); + fail_if (gst_rtsp_token_is_allowed (token, "permission2")); + fail_unless_equals_string (gst_rtsp_token_get_string (token, "role"), "user"); + + fail_unless (gst_mini_object_is_writable (GST_MINI_OBJECT (token))); + fail_unless (gst_rtsp_token_writable_structure (token) != NULL); + fail_unless (gst_rtsp_token_get_structure (token) != NULL); + + token2 = gst_rtsp_token_ref (token); + + fail_if (gst_mini_object_is_writable (GST_MINI_OBJECT (token))); + ASSERT_CRITICAL (fail_unless (gst_rtsp_token_writable_structure (token) == + NULL)); + fail_unless (gst_rtsp_token_get_structure (token) != NULL); + + gst_rtsp_token_unref (token2); + + fail_unless (gst_mini_object_is_writable (GST_MINI_OBJECT (token))); + fail_unless (gst_rtsp_token_writable_structure (token) != NULL); + fail_unless (gst_rtsp_token_get_structure (token) != NULL); + + str = gst_rtsp_token_writable_structure (token); + gst_structure_set (str, "permission2", G_TYPE_BOOLEAN, TRUE, NULL); + fail_unless_equals_string (gst_rtsp_token_get_string (token, "role"), "user"); + fail_unless (gst_rtsp_token_is_allowed (token, "permission1")); + fail_unless (gst_rtsp_token_is_allowed (token, "permission2")); + fail_unless_equals_string (gst_rtsp_token_get_string (token, "role"), "user"); + gst_rtsp_token_unref (token); +} + +GST_END_TEST; + +static Suite * +rtsptoken_suite (void) +{ + Suite *s = suite_create ("rtsptoken"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_set_timeout (tc, 20); + tcase_add_test (tc, test_token); + + return s; +} + +GST_CHECK_MAIN (rtsptoken); diff --git a/tests/test-cleanup.c b/tests/test-cleanup.c new file mode 100644 index 0000000..3b6f7f6 --- /dev/null +++ b/tests/test-cleanup.c @@ -0,0 +1,68 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + +static gboolean +timeout (GMainLoop * loop, gboolean ignored) +{ + g_main_loop_quit (loop); + return FALSE; +} + + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GstRTSPServer *server; + guint id; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* attach the server to the default maincontext */ + if ((id = gst_rtsp_server_attach (server, NULL)) == 0) + goto failed; + + g_timeout_add_seconds (2, (GSourceFunc) timeout, loop); + + /* start serving */ + g_main_loop_run (loop); + + /* cleanup */ + g_source_remove (id); + g_object_unref (server); + g_main_loop_unref (loop); + + return 0; + + /* ERRORS */ +failed: + { + g_print ("failed to attach the server\n"); + return -1; + } +} diff --git a/tests/test-reuse.c b/tests/test-reuse.c new file mode 100644 index 0000000..67063a8 --- /dev/null +++ b/tests/test-reuse.c @@ -0,0 +1,90 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * 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. + */ + +#include + +#include + +#define TIMEOUT 2 + +static gboolean timeout_1 (GMainLoop * loop, gboolean ignored); + +static guint id; +static gint rounds = 3; +static GstRTSPServer *server; + +static gboolean +timeout_2 (GMainLoop * loop, gboolean ignored) +{ + rounds--; + if (rounds > 0) { + id = gst_rtsp_server_attach (server, NULL); + g_print ("have attached\n"); + g_timeout_add_seconds (TIMEOUT, (GSourceFunc) timeout_1, loop); + } else { + g_main_loop_quit (loop); + } + return FALSE; +} + +static gboolean +timeout_1 (GMainLoop * loop, gboolean ignored) +{ + g_source_remove (id); + g_print ("have removed\n"); + g_timeout_add_seconds (TIMEOUT, (GSourceFunc) timeout_2, loop); + return FALSE; +} + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + /* create a server instance */ + server = gst_rtsp_server_new (); + + /* attach the server to the default maincontext */ + if ((id = gst_rtsp_server_attach (server, NULL)) == 0) + goto failed; + g_print ("have attached\n"); + + g_timeout_add_seconds (TIMEOUT, (GSourceFunc) timeout_1, loop); + + /* start serving */ + g_main_loop_run (loop); + + /* cleanup */ + g_object_unref (server); + g_main_loop_unref (loop); + + g_print ("quit\n"); + return 0; + + /* ERRORS */ +failed: + { + g_print ("failed to attach the server\n"); + return -1; + } +}