Repository: 01org/wds Branch: master Commit: 2d7db6cd406e Files: 190 Total size: 543.7 KB Directory structure: gitextract_id6ruww0/ ├── CMakeLists.txt ├── COPYING ├── README.md ├── TODO ├── data/ │ ├── CMakeLists.txt │ └── wds.pc.in ├── datadumps/ │ ├── gstreamer-pipelines.txt │ ├── information-elements.pcapng │ └── rtsp-capture-win8.txt ├── desktop_source/ │ ├── CMakeLists.txt │ ├── desktop_media_manager.cpp │ ├── desktop_media_manager.h │ ├── main.cpp │ ├── mirac_broker_source.cpp │ ├── mirac_broker_source.h │ ├── source-app.cpp │ └── source-app.h ├── libwds/ │ ├── CMakeLists.txt │ ├── common/ │ │ ├── CMakeLists.txt │ │ ├── logging.cpp │ │ ├── message_handler.cpp │ │ ├── message_handler.h │ │ ├── rtsp_input_handler.cpp │ │ ├── rtsp_input_handler.h │ │ └── video_format.cpp │ ├── public/ │ │ ├── audio_codec.h │ │ ├── connector_type.h │ │ ├── logging.h │ │ ├── media_manager.h │ │ ├── peer.h │ │ ├── sink.h │ │ ├── source.h │ │ ├── video_format.h │ │ └── wds_export.h │ ├── rtsp/ │ │ ├── CMakeLists.txt │ │ ├── audiocodecs.cpp │ │ ├── audiocodecs.h │ │ ├── avformatchangetiming.cpp │ │ ├── avformatchangetiming.h │ │ ├── clientrtpports.cpp │ │ ├── clientrtpports.h │ │ ├── connectortype.cpp │ │ ├── connectortype.h │ │ ├── constants.h │ │ ├── contentprotection.cpp │ │ ├── contentprotection.h │ │ ├── coupledsink.cpp │ │ ├── coupledsink.h │ │ ├── displayedid.cpp │ │ ├── displayedid.h │ │ ├── driver.cpp │ │ ├── driver.h │ │ ├── errorlexer.l │ │ ├── formats3d.cpp │ │ ├── formats3d.h │ │ ├── genericproperty.cpp │ │ ├── genericproperty.h │ │ ├── getparameter.cpp │ │ ├── getparameter.h │ │ ├── header.cpp │ │ ├── header.h │ │ ├── headerlexer.l │ │ ├── i2c.cpp │ │ ├── i2c.h │ │ ├── idrrequest.cpp │ │ ├── idrrequest.h │ │ ├── macros.h │ │ ├── message.cpp │ │ ├── message.h │ │ ├── messagelexer.l │ │ ├── messages_rules.txt │ │ ├── options.cpp │ │ ├── options.h │ │ ├── parser.ypp │ │ ├── pause.cpp │ │ ├── pause.h │ │ ├── payload.cpp │ │ ├── payload.h │ │ ├── play.cpp │ │ ├── play.h │ │ ├── preferreddisplaymode.cpp │ │ ├── preferreddisplaymode.h │ │ ├── presentationurl.cpp │ │ ├── presentationurl.h │ │ ├── property.cpp │ │ ├── property.h │ │ ├── propertyerrors.cpp │ │ ├── propertyerrors.h │ │ ├── reply.cpp │ │ ├── reply.h │ │ ├── route.cpp │ │ ├── route.h │ │ ├── setparameter.cpp │ │ ├── setparameter.h │ │ ├── setup.cpp │ │ ├── setup.h │ │ ├── standby.cpp │ │ ├── standby.h │ │ ├── standbyresumecapability.cpp │ │ ├── standbyresumecapability.h │ │ ├── teardown.cpp │ │ ├── teardown.h │ │ ├── tests/ │ │ │ ├── CMakeLists.txt │ │ │ ├── README │ │ │ ├── dict/ │ │ │ │ ├── wfd_header.dict │ │ │ │ ├── wfd_payload_error.dict │ │ │ │ ├── wfd_payload_reply.dict │ │ │ │ └── wfd_payload_request.dict │ │ │ ├── run_afl_fuzzer.sh │ │ │ ├── seed/ │ │ │ │ ├── header/ │ │ │ │ │ ├── error.txt │ │ │ │ │ ├── get_parameter.txt │ │ │ │ │ ├── options.txt │ │ │ │ │ ├── pause.txt │ │ │ │ │ ├── play.txt │ │ │ │ │ ├── reply.txt │ │ │ │ │ ├── set_parameter.txt │ │ │ │ │ ├── setup.txt │ │ │ │ │ └── teardown.txt │ │ │ │ ├── payload_error/ │ │ │ │ │ ├── payload_error01.txt │ │ │ │ │ └── payload_error02.txt │ │ │ │ ├── payload_reply/ │ │ │ │ │ ├── payload_reply01.txt │ │ │ │ │ └── payload_reply02.txt │ │ │ │ └── payload_request/ │ │ │ │ ├── payload_request01.txt │ │ │ │ └── payload_request02.txt │ │ │ ├── tests.cpp │ │ │ └── wdsfuzzer.cpp │ │ ├── transportheader.cpp │ │ ├── transportheader.h │ │ ├── triggermethod.cpp │ │ ├── triggermethod.h │ │ ├── uibccapability.cpp │ │ ├── uibccapability.h │ │ ├── uibcsetting.cpp │ │ ├── uibcsetting.h │ │ ├── videoformats.cpp │ │ └── videoformats.h │ ├── sink/ │ │ ├── CMakeLists.txt │ │ ├── cap_negotiation_state.cpp │ │ ├── cap_negotiation_state.h │ │ ├── init_state.cpp │ │ ├── init_state.h │ │ ├── session_state.cpp │ │ ├── session_state.h │ │ ├── sink.cpp │ │ ├── streaming_state.cpp │ │ └── streaming_state.h │ └── source/ │ ├── CMakeLists.txt │ ├── cap_negotiation_state.cpp │ ├── cap_negotiation_state.h │ ├── init_state.cpp │ ├── init_state.h │ ├── session_state.cpp │ ├── session_state.h │ ├── source.cpp │ ├── streaming_state.cpp │ └── streaming_state.h ├── mirac_network/ │ ├── CMakeLists.txt │ ├── gst-test.cpp │ ├── mirac-broker.cpp │ ├── mirac-broker.hpp │ ├── mirac-exception.hpp │ ├── mirac-glib-logging.cpp │ ├── mirac-glib-logging.hpp │ ├── mirac-gst-bus-handler.cpp │ ├── mirac-gst-bus-handler.hpp │ ├── mirac-gst-sink.cpp │ ├── mirac-gst-sink.hpp │ ├── mirac-gst-test-source.cpp │ ├── mirac-gst-test-source.hpp │ ├── mirac-network.cpp │ ├── mirac-network.hpp │ └── network-test.cpp ├── p2p/ │ ├── CMakeLists.txt │ ├── connman-client.cpp │ ├── connman-client.h │ ├── connman-peer.cpp │ ├── connman-peer.h │ ├── information-element.cpp │ ├── information-element.h │ ├── main.cpp │ └── test-ie.cpp ├── rtsp-message-exchanges.txt └── sink/ ├── CMakeLists.txt ├── gst_sink_media_manager.cpp ├── gst_sink_media_manager.h ├── main.cpp ├── sink-app.cpp ├── sink-app.h ├── sink.cpp └── sink.h ================================================ FILE CONTENTS ================================================ ================================================ FILE: CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(wds CXX) set(WDS_VERSION_MAJOR 1) set(WDS_VERSION_MINOR 1) set(WDS_VERSION_PATCH 0) enable_testing() option(WDS_INSTALL_TESTS "Install test programs" off) include(GNUInstallDirs) add_subdirectory(data) add_subdirectory(libwds/rtsp) add_subdirectory(libwds/rtsp/tests) add_subdirectory(libwds/common) add_subdirectory(libwds/source) add_subdirectory(libwds/sink) add_subdirectory(libwds) add_subdirectory(p2p) add_subdirectory(mirac_network) add_subdirectory(sink) add_subdirectory(desktop_source) ================================================ FILE: COPYING ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: README.md ================================================ DISCONTINUATION OF PROJECT. This project will no longer be maintained by Intel. Intel has ceased development and contributions including, but not limited to, maintenance, bug fixes, new releases, or updates, to this project. Intel no longer accepts patches to this project. If you have an ongoing need to use this project, are interested in independently developing it, or would like to maintain patches for the open source software community, please create your own fork of this project. ## Wireless Display Software For Linux OS (WDS) WDS is a set of libraries for developers who want to build Wi-Fi Display applications on linux. WDS consists of: * libwds: Main library implements a Wi-Fi Display dialect of RTSP that includes the parser, actual negotiation logic for sink and source, and the related data structures. It is not tied to any specific connection manager, media framework or main loop. This Library is also compatible with MSVC. * network: Supports integration with GLib main loop and GStreamer * p2p: Supports integration with Connman Wifi P2P features The source code includes example implementations: * _sink:_ Wi-Fi Display sink that depends on Gstreamer, Connman and GLib mainloop * _desktop_source:_ Wi-Fi Display source that depends on Gstreamer, Connman and GLib mainloop More information can be found on the [mailing list](https://lists.01.org/mailman/listinfo/wysiwidi-dev) and the [wiki](https://github.com/01org/wds/wiki). ### Requirements: WDS test executables have runtime dependencies on just a few things (mostly GStreamer and GLib), but for successful Wi-Fi Display sessions the following are adviced: * Wifi adapter from Intel 7260-family or Atheros ath9k * [wpa_supplicant](http://w1.fi/wpa_supplicant/): version 2.4 or later, built with `CONFIG_P2P=y`, `CONFIG_WIFI_DISPLAY=y` and `CONFIG_CTRL_IFACE_DBUS_NEW=y` * [connman](https://01.org/connman): version 1.28 (released Feb 1st 2015) or later. * gstreamer: either master branch more recent than Feb 3rd 2015 (commit d0a50be2), or 1.4 branch more recent than Feb 3rd 2005 (commit 1ce3260a638d or release 1.4.6 or later). Test results with other Wifi adapters are very welcome but be warned that in many cases Wifi-P2P has not had the testing it needs on linux: you may run into problems in surprising places. ### Building WDS from git: ``` cmake . make ``` ### Testing WDS #### Pre-requisites Make sure wpa_supplicant & connmand are running. Running both of them uninstalled is possible (but in that case make sure the system wpa_supplicant and system connection manager are _not_ running): ``` $ sudo hostap/wpa_supplicant/wpa_supplicant -ddt -u $ sudo connman/src/connmand -n -d ``` Use connmanctl to enable Wi-Fi and Wi-Fi P2P: ``` $ connman/client/connmanctl connmanctl> enable wifi Enabled wifi connmanctl> enable p2p Enabled p2p ``` Check that Peer-to-peer functionality is working: ``` connmanctl> scan p2p Scan completed for p2p connmanctl> peers Nexus 5 (jku) idle peer_0c8bfd5f12fc_8ac9d0c0da67 Push2TV 75AEB2-PTV3000 idle peer_0c8bfd5f12fc_22e52a75aeb2 ``` Enable agent: ``` connmanctl> agent on Agent registered ``` #### Testing WDS sink with an Android device (e.g. Nexus 5): * start sink: `sink/sink-test` * Android: select the sink from the list in "Settings > Display > Cast Screen" * connmanctl: when agent asks, accept the connection In a few seconds, a window should open and a audio/video stream should start playing. #### Testing WDS source with another sink: * start source: `desktop_source/desktop_source` * Initial scan will be automatic, but `scan` command will re-scan. * After getting scan results, connect with `connect N` (where N is number from scan result) * connmanctl: when agent asks, accept the connection In a few seconds, the sink should start showing a stream mirroring your desktop. ================================================ FILE: TODO ================================================ GOAL: Make a release with the proper librarization by the time all dependencies are released, namely a. wpa_supplicant, past 2.3 (likely 2.4) b. connman, past 1.28 (likely 1.29) c. gst_plugins_bad past 1.4.5+ (likely 1.4.6) Big tasks (see issue tracker for the rest) ========================================== Inspect and beautify P2P API Create an installable library from the current source tree Create C/gobject interface to the library so that language bindings can be done easliy Create API for HDCP plugin implementation Implement UIBC Use accelerated encoders/decoders for demo apps ================================================ FILE: data/CMakeLists.txt ================================================ configure_file(wds.pc.in wds.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/wds.pc DESTINATION lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig) ================================================ FILE: data/wds.pc.in ================================================ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ includedir=${exec_prefix}/include Name: @CMAKE_PROJECT_NAME@ Description: Library to build WiFi Display applications Version: @WDS_VERSION_MAJOR@.@WDS_VERSION_MINOR@.@WDS_VERSION_PATCH@ Libs: -L${libdir} -lwds Cflags: -I${includedir}/wds ================================================ FILE: datadumps/gstreamer-pipelines.txt ================================================ WFD source: Only video: gst-launch-1.0 videotestsrc ! x264enc ! mpegtsmux ! rtpmp2tpay ! udpsink host=127.0.0.1 port=5000 Only audio: gst-launch-1.0 audiotestsrc ! avenc_ac3 ! mpegtsmux ! rtpmp2tpay ! udpsink host=127.0.0.1 port=5000 Both: gst-launch-1.0 videotestsrc ! x264enc ! muxer. audiotestsrc ! avenc_ac3 ! muxer. mpegtsmux name=muxer ! rtpmp2tpay ! udpsink host=127.0.0.1 port=5000 WFD sink: Only audio: gst-launch-1.0 udpsrc port=5000 caps="application/x-rtp" ! rtpmp2tdepay ! decodebin ! autoaudiosink Only video: gst-launch-1.0 udpsrc port=5000 caps="application/x-rtp" ! rtpmp2tdepay ! decodebin ! autovideosink Both: gst-launch-1.0 udpsrc port=5000 caps="application/x-rtp" ! rtpmp2tdepay ! decodebin name=decoder ! autoaudiosink decoder. ! autovideosink ================================================ FILE: datadumps/rtsp-capture-win8.txt ================================================ OPTIONS * RTSP/1.0 CSeq: 1 Require: org.wfa.wfd1.0 User-Agent: WiDiApp/4.5.35.0 RDS/1.0.0 RTSP/1.0 200 OK CSeq: 1 Date: Thu Jan 1 00:05:42 1970 Public: org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER OPTIONS * RTSP/1.0 CSeq: 1 Require: org.wfa.wfd1.0 User-Agent: SEC-WDH/ME29 RTSP/1.0 200 OK CSeq: 1 Date: Tue, Aug 05 2014 18:56:28 GMT Public: org.wfa.wfd1.0, GET_PARAMETER, PAUSE, PLAY, SETUP, SET_PARAMETER, TEARDOWN GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: 2 Content-Type: text/parameters Content-Length: 325 wfd_client_rtp_ports wfd_audio_codecs wfd_video_formats wfd_3d_video_formats wfd_coupled_sink wfd_display_edid wfd_connector_type wfd_uibc_capability wfd_standby_resume_capability wfd_content_protection intel_sink_version intel_sink_information intel_lower_bandwidth intel_interactivity_mode intel_fast_cursor RTSP/1.0 200 OK CSeq: 2 Content-Type: text/parameters Content-Length: 1187 wfd_audio_codecs: LPCM 00000003 00, AAC 00000001 00 wfd_video_formats: 40 00 02 04 0001DEFF 053C7FFF 00000FFF 00 0000 0000 11 none none, 01 04 0001DEFF 053C7FFF 00000FFF 00 0000 0000 11 none none wfd_3d_video_formats: 80 00 03 0F 0000000000000005 00 0001 1401 13 none none wfd_content_protection: HDCP2.1 port=1189 wfd_display_edid: 0002 00ffffffffffff004c2dde07000000002f14010380834a780aee91a3544c99260f5054bdef80714f8100814081809500950fb300a940023a801871382d40582c4500a05a0000001e662150b051001b3040703600a05a0000001e000000fd00184b1a5117000a202020202020000000fc0053414d53554e470a202020202001fd02032ef14b901f0413051403122021222309070783010000e2000f72030c004000b82d20d0080140073f405090a0023a80d072382d40102c4580a05a0000001e011d00bc52d01e20b8285540a05a0000001e011d80d0721c1620102c2580a05a0000009e00000000000000000000000000000000000000000000000000000078 wfd_coupled_sink: none wfd_client_rtp_ports: RTP/AVP/UDP;unicast 19000 0 mode=play wfd_uibc_capability: none wfd_connector_type: 05 wfd_standby_resume_capability: supported intel_sink_version: product_ID=widicesdk hw_version=02.00.00.0000 sw_version=02.04.46.0000 intel_lower_bandwidth: none intel_interactivity_mode: HIGH SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: 3 Content-Type: text/parameters Content-Length: 248 wfd_audio_codecs: AAC 00000001 00 wfd_video_formats: 00 00 02 04 00000020 00000000 00000000 00 0000 0000 11 none none wfd_presentation_URL: rtsp://192.168.173.1/wfd1.0/streamid=0 none wfd_client_rtp_ports: RTP/AVP/UDP;unicast 19000 0 mode=play RTSP/1.0 200 OK CSeq: 3 SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: 4 Content-Type: text/parameters Content-Length: 146 intel_overscan_comp: x=0, y=0 intel_sigma_pipeline_params: PlaybackDelay=50; PositiveMaxStcPCR=25; NegativeMaxStcPCR=50; intel_topology: CLONE RTSP/1.0 200 OK CSeq: 4 SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: 5 Content-Type: text/parameters Content-Length: 27 wfd_trigger_method: SETUP RTSP/1.0 200 OK CSeq: 5 SETUP rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: 2 User-Agent: SEC-WDH/ME29 Transport: RTP/AVP/UDP;unicast;client_port=19000 RTSP/1.0 200 OK CSeq: 2 Session: VaMkltjy;timeout=60 Transport: RTP/AVP/UDP;unicast;client_port=19000;server_port=53151-53153 PLAY rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: 3 Session: VaMkltjy User-Agent: SEC-WDH/ME29 RTSP/1.0 200 OK CSeq: 3 Session: VaMkltjy Date: Tue, Aug 05 2014 18:56:29 GMT SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: 6 Content-Type: text/parameters Content-Length: 31 Session: VaMkltjy intel_enable_widi_rtcp: 53153 RTSP/1.0 200 OK CSeq: 6 SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: 7 Content-Type: text/parameters Content-Length: 172 Session: VaMkltjy wfd_audio_codecs: AAC 00000001 00 wfd_video_formats: 00 00 02 04 00000000 00001000 00000000 00 0000 0000 11 none none wfd_av_format_change_timing: 00000bb800 000005dc00 RTSP/1.0 200 OK CSeq: 7 SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: 8 Content-Type: text/parameters Content-Length: 150 Session: VaMkltjy intel_sigma_pipeline_params: PlaybackDelay=50; PositiveMaxStcPCR=25; NegativeMaxStcPCR=50; intel_interactivity_mode: DEFAULT intel_topology: LOCAL RTSP/1.0 200 OK CSeq: 8 SET_PARAMETER rtsp://192.168.173.1/wfd1.0/streamid=0 RTSP/1.0 CSeq: 4 Session: VaMkltjy User-Agent: SEC-WDH/ME29 Content-Type: text/parameters Content-Length: 17 wfd_idr_request RTSP/1.0 200 OK CSeq: 4 Session: VaMkltjy SET_PARAMETER rtsp://192.168.173.1/wfd1.0/streamid=0 RTSP/1.0 CSeq: 5 Session: VaMkltjy User-Agent: SEC-WDH/ME29 Content-Type: text/parameters Content-Length: 17 wfd_idr_request RTSP/1.0 200 OK CSeq: 5 Session: VaMkltjy SET_PARAMETER rtsp://192.168.173.1/wfd1.0/streamid=0 RTSP/1.0 CSeq: 6 Session: VaMkltjy User-Agent: SEC-WDH/ME29 Content-Type: text/parameters Content-Length: 17 wfd_idr_request RTSP/1.0 200 OK CSeq: 6 Session: VaMkltjy SET_PARAMETER rtsp://192.168.173.1/wfd1.0/streamid=0 RTSP/1.0 CSeq: 7 Session: VaMkltjy User-Agent: SEC-WDH/ME29 Content-Type: text/parameters Content-Length: 17 wfd_idr_request RTSP/1.0 200 OK CSeq: 7 Session: VaMkltjy SET_PARAMETER rtsp://192.168.173.1/wfd1.0/streamid=0 RTSP/1.0 CSeq: 8 Session: VaMkltjy User-Agent: SEC-WDH/ME29 Content-Type: text/parameters Content-Length: 17 wfd_idr_request RTSP/1.0 200 OK CSeq: 8 Session: VaMkltjy SET_PARAMETER rtsp://192.168.173.1/wfd1.0/streamid=0 RTSP/1.0 CSeq: 9 Session: VaMkltjy User-Agent: SEC-WDH/ME29 Content-Type: text/parameters Content-Length: 17 wfd_idr_request RTSP/1.0 200 OK CSeq: 9 Session: VaMkltjy SET_PARAMETER rtsp://192.168.173.1/wfd1.0/streamid=0 RTSP/1.0 CSeq: 10 Session: VaMkltjy User-Agent: SEC-WDH/ME29 Content-Type: text/parameters Content-Length: 17 wfd_idr_request RTSP/1.0 200 OK CSeq: 10 Session: VaMkltjy ================================================ FILE: desktop_source/CMakeLists.txt ================================================ #FIXME in the future: with cmake 2.8.12 and up it's better #to use target_compile_options or add_compile_options set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pthread -std=c++11") include_directories ("${PROJECT_SOURCE_DIR}") include_directories ("${PROJECT_SOURCE_DIR}/libwds/public") include_directories ("${PROJECT_SOURCE_DIR}/libwds/parser") include_directories ("${PROJECT_SOURCE_DIR}/p2p") include_directories ("${PROJECT_SOURCE_DIR}/mirac_network") find_package(PkgConfig REQUIRED) pkg_check_modules (GLIB2 REQUIRED glib-2.0) include_directories(${GLIB2_INCLUDE_DIRS}) pkg_check_modules (GIO REQUIRED gio-2.0) include_directories(${GIO_INCLUDE_DIRS}) pkg_check_modules (GST REQUIRED gstreamer-1.0) include_directories(${GST_INCLUDE_DIRS}) add_executable(desktop-source-test main.cpp source-app.cpp mirac_broker_source.cpp desktop_media_manager.cpp) target_link_libraries (desktop-source-test mirac wds p2p ${GIO_LIBRARIES} ${GST_LIBRARIES}) if (WDS_INSTALL_TESTS) install(PROGRAMS desktop-source-test DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}) endif() ================================================ FILE: desktop_source/desktop_media_manager.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "desktop_media_manager.h" #include "mirac-glib-logging.hpp" #include DesktopMediaManager::DesktopMediaManager(const std::string& hostname) : hostname_(hostname), format_() { } void DesktopMediaManager::Play() { assert(gst_pipeline_); gst_pipeline_->SetState(GST_STATE_PLAYING); } void DesktopMediaManager::Pause() { assert(gst_pipeline_); gst_pipeline_->SetState(GST_STATE_PAUSED); } void DesktopMediaManager::Teardown() { if (gst_pipeline_) gst_pipeline_->SetState(GST_STATE_READY); } bool DesktopMediaManager::IsPaused() const { return (gst_pipeline_->GetState() != GST_STATE_PLAYING); } std::string DesktopMediaManager::GetSessionId() const { return "abcdefg123456"; } wds::SessionType DesktopMediaManager::GetSessionType() const { return wds::VideoSession; } void DesktopMediaManager::SetSinkRtpPorts(int port1, int port2) { sink_port1_ = port1; sink_port2_ = port2; gst_pipeline_.reset(new MiracGstTestSource(WFD_DESKTOP, hostname_, port1)); gst_pipeline_->SetState(GST_STATE_READY); } std::pair DesktopMediaManager::GetSinkRtpPorts() const { return std::pair(sink_port1_, sink_port2_); } int DesktopMediaManager::GetLocalRtpPort() const { return gst_pipeline_->UdpSourcePort(); } namespace { std::vector GetH264VideoCodecs() { static std::vector codecs; if (codecs.empty()) { wds::RateAndResolutionsBitmap cea_rr; wds::RateAndResolutionsBitmap vesa_rr; wds::RateAndResolutionsBitmap hh_rr; wds::RateAndResolution i; // declare that we support all resolutions, CHP and level 4.2 // gstreamer should handle all of it :) for (i = wds::CEA640x480p60; i <= wds::CEA1920x1080p24; ++i) cea_rr.set(i); for (i = wds::VESA800x600p30; i <= wds::VESA1920x1200p30; ++i) vesa_rr.set(i); for (i = wds::HH800x480p30; i <= wds::HH848x480p60; ++i) hh_rr.set(i); wds::H264VideoCodec codec(wds::CHP, wds::k4_2, cea_rr, vesa_rr, hh_rr); codecs.push_back(codec); } return codecs; } } bool DesktopMediaManager::InitOptimalVideoFormat( const wds::NativeVideoFormat& sink_native_format, const std::vector& sink_supported_codecs) { format_ = wds::FindOptimalVideoFormat(sink_native_format, GetH264VideoCodecs(), sink_supported_codecs); return true; } wds::H264VideoFormat DesktopMediaManager::GetOptimalVideoFormat() const { return format_; } bool DesktopMediaManager::InitOptimalAudioFormat(const std::vector& sink_codecs) { for (const auto& codec : sink_codecs) { if (codec.format == wds::AAC && codec.modes.test(wds::AAC_48K_16B_2CH)) return true; } return false; } wds::AudioCodec DesktopMediaManager::GetOptimalAudioFormat() const { wds::AudioModes audio_modes; audio_modes.set(wds::AAC_48K_16B_2CH); return wds::AudioCodec(wds::AAC, audio_modes, 0); } void DesktopMediaManager::SendIDRPicture() { WDS_WARNING("Unimplemented IDR picture request"); } ================================================ FILE: desktop_source/desktop_media_manager.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef DESKTOP_MEDIA_MANAGER_H_ #define DESKTOP_MEDIA_MANAGER_H_ #include #include "libwds/public/media_manager.h" #include "mirac-gst-test-source.hpp" class DesktopMediaManager : public wds::SourceMediaManager { public: explicit DesktopMediaManager(const std::string& hostname); void Play() override; void Pause() override; void Teardown() override; bool IsPaused() const override; std::string GetSessionId() const override; void SetSinkRtpPorts(int port1, int port2) override; std::pair GetSinkRtpPorts() const override; int GetLocalRtpPort() const override; wds::SessionType GetSessionType() const override; bool InitOptimalVideoFormat(const wds::NativeVideoFormat& sink_native_format, const std::vector& sink_supported_codecs) override; wds::H264VideoFormat GetOptimalVideoFormat() const override; bool InitOptimalAudioFormat(const std::vector& sink_supported_codecs) override; wds::AudioCodec GetOptimalAudioFormat() const override; void SendIDRPicture() override; private: std::string hostname_; std::unique_ptr gst_pipeline_; int sink_port1_; int sink_port2_; wds::H264VideoFormat format_; }; #endif // DESKTOP_MEDIA_MANAGER_H_ ================================================ FILE: desktop_source/main.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include "source-app.h" #include "mirac_broker_source.h" #include "mirac-glib-logging.hpp" #include "libwds/public/source.h" static gboolean _sig_handler (gpointer data_ptr) { GMainLoop *main_loop = (GMainLoop *) data_ptr; g_main_loop_quit(main_loop); return G_SOURCE_CONTINUE; } static void parse_input_and_call_source( const std::string& command, SourceApp *app) { auto source = app->source()->wfd_source(); bool status = true; if (command == "scan\n") { app->scan(); } else if (command.find("connect ") == 0) { app->connect(std::stoi(command.substr(8))); } else if (command == "teardown\n") { status = source && source->Teardown(); } else if (command == "pause\n") { status = source && source->Pause(); } else if (command == "play\n") { status = source && source->Play(); } else { std::cout << "Received unknown command: " << command << std::endl; } if (!status) std::cout << "This command cannot be executed now." << std::endl; } static gboolean _user_input_handler ( GIOChannel* channel, GIOCondition /*condition*/, gpointer data_ptr) { GError* error = NULL; char* str = NULL; size_t len; SourceApp* app = static_cast(data_ptr); switch (g_io_channel_read_line(channel, &str, &len, NULL, &error)) { case G_IO_STATUS_NORMAL: parse_input_and_call_source(str, app); g_free(str); return true; case G_IO_STATUS_ERROR: std::cout << "User input error: " << error->message << std::endl; g_error_free(error); return false; case G_IO_STATUS_EOF: case G_IO_STATUS_AGAIN: return true; default: return false; } return false; } int main (int argc, char *argv[]) { InitGlibLogging(); int port = 7236; GOptionEntry main_entries[] = { { "rtsp_port", 0, 0, G_OPTION_ARG_INT, &(port), "Specify optional RTSP port number, 7236 by default", "rtsp_port"}, { NULL } }; GOptionContext* context = g_option_context_new ("- WFD desktop source demo application\n"); g_option_context_add_main_entries (context, main_entries, NULL); g_option_context_add_group (context, gst_init_get_option_group ()); GError* error = NULL; if (!g_option_context_parse (context, &argc, &argv, &error)) { WDS_ERROR ("option parsing failed: %s", error->message); g_option_context_free(context); exit (1); } g_option_context_free(context); SourceApp app(port); GMainLoop *main_loop = g_main_loop_new(NULL, TRUE); g_unix_signal_add(SIGINT, _sig_handler, main_loop); g_unix_signal_add(SIGTERM, _sig_handler, main_loop); GIOChannel* io_channel = g_io_channel_unix_new (STDIN_FILENO); g_io_add_watch(io_channel, G_IO_IN, _user_input_handler, &app); g_io_channel_unref(io_channel); g_main_loop_run (main_loop); g_main_loop_unref (main_loop); return 0; } ================================================ FILE: desktop_source/mirac_broker_source.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include "desktop_media_manager.h" #include "mirac_broker_source.h" #include "libwds/public/source.h" MiracBrokerSource::MiracBrokerSource(int rtsp_port) : MiracBroker(std::to_string(rtsp_port)) { } MiracBrokerSource::~MiracBrokerSource() {} void MiracBrokerSource::got_message(const std::string& message) { wfd_source_->RTSPDataReceived(message); } void MiracBrokerSource::on_connected() { media_manager_.reset(new DesktopMediaManager(get_peer_address())); wfd_source_.reset(wds::Source::Create(this, media_manager_.get())); wfd_source_->Start(); } void MiracBrokerSource::on_connection_failure(ConnectionFailure failure) { switch (failure) { case CONNECTION_LOST: std::cout << "* RTSP connection lost" << std::endl; break; case CONNECTION_TIMEOUT: std::cout << "* RTSP connection failed: timeout" << std::endl; break; default: std::cout << "* RTSP connection failure" << std::endl; } } wds::Peer* MiracBrokerSource::Peer() const { return wfd_source_.get(); } ================================================ FILE: desktop_source/mirac_broker_source.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef MIRAC_BROKER_SOURCE_H_ #define MIRAC_BROKER_SOURCE_H_ #include #include "mirac-broker.hpp" namespace wds { class SourceMediaManager; class Source; } class MiracBrokerSource : public MiracBroker { public: explicit MiracBrokerSource(int rtsp_port); ~MiracBrokerSource(); wds::Source* wfd_source() { return wfd_source_.get(); } private: virtual void got_message(const std::string& message) override; virtual void on_connected() override; void on_connection_failure(ConnectionFailure failure) override; virtual wds::Peer* Peer() const override; std::unique_ptr media_manager_; std::unique_ptr wfd_source_; }; #endif // MIRAC_BROKER_SOURCE_H_ ================================================ FILE: desktop_source/source-app.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include // htons() #include "source-app.h" void SourceApp::on_availability_changed(P2P::Client *client) { if (client->is_available()) scan(); } void SourceApp::on_peer_added(P2P::Client *client, std::shared_ptr peer) { if (peer->device_type() == P2P::PRIMARY_SINK) { peer->set_observer(this); } } void SourceApp::on_peer_removed(P2P::Client *client, std::shared_ptr peer) { for (auto it = peers_.begin(); it != peers_.end();) { if (it->second == peer.get()) { peers_.erase (it++); return; } else { ++it; } } } void SourceApp::on_initialized(P2P::Peer *peer) { peers_[peer_index_] = peer; std::cout << " "<< peer_index_ << " : " << peer->name() << std::endl; peer_index_++; } void SourceApp::scan() { std::cout << "* Now scanning for peers..." << std::endl; p2p_client_->scan(); } bool SourceApp::connect(uint peer_index) { auto it = peers_.find (peer_index); if (it == peers_.end()) { std::cout << "No such peer" << std::endl; return false; } it->second->connect (); return true; } void SourceApp::on_availability_changed(P2P::Peer *peer) { if (!peer->is_available()) return; std::cout << "* Connected to " << peer->remote_host() << std::endl; } SourceApp::SourceApp(int port) : peer_index_(0) { // Create a information element for a simple WFD Source P2P::InformationElement ie; auto sub_element = P2P::new_subelement(P2P::DEVICE_INFORMATION); auto dev_info = (P2P::DeviceInformationSubelement*)sub_element; // TODO InformationElement could have constructors for this stuff... dev_info->session_management_control_port = htons(port); dev_info->maximum_throughput = htons(50); dev_info->field1.device_type = P2P::SOURCE; dev_info->field1.session_availability = true; ie.add_subelement(sub_element); std::cout << "* Registering Wi-Fi Display Source with IE " << ie.to_string() << std::endl; // register the P2P service with connman auto array = ie.serialize (); p2p_client_.reset(new P2P::Client(array, this)); source_.reset(new MiracBrokerSource(port)); } SourceApp::~SourceApp() { } ================================================ FILE: desktop_source/source-app.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SOURCE_APP_H #define SOURCE_APP_H #include #include "source.h" #include "connman-client.h" #include "mirac_broker_source.h" class SourceApp: public P2P::Client::Observer, public P2P::Peer::Observer { public: SourceApp(int port); ~SourceApp(); MiracBrokerSource* source() { return source_.get(); } void on_peer_added(P2P::Client *client, std::shared_ptr peer) override; void on_peer_removed(P2P::Client *client, std::shared_ptr peer) override; void on_availability_changed(P2P::Client *client) override; void on_availability_changed(P2P::Peer *peer) override; void on_initialized(P2P::Peer *peer) override; void scan(); bool connect(uint peer_index); private: std::unique_ptr p2p_client_; std::unique_ptr source_; std::mappeers_; uint peer_index_; }; #endif // SOURCE_APP_H ================================================ FILE: libwds/CMakeLists.txt ================================================ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fvisibility=hidden") set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -std=c99 -Wall") add_library(wds SHARED $ $ $ $) set_target_properties(wds PROPERTIES VERSION ${WDS_VERSION_MAJOR}.${WDS_VERSION_MINOR}.${WDS_VERSION_PATCH} SOVERSION ${WDS_VERSION_MAJOR}) install(TARGETS wds LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) set(PUBLIC_HEADERS public/connector_type.h public/peer.h public/video_format.h public/sink.h public/wds_export.h public/audio_codec.h public/media_manager.h public/source.h public/logging.h) install(FILES ${PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/wds) ================================================ FILE: libwds/common/CMakeLists.txt ================================================ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fvisibility=hidden -fPIC") set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -std=c99 -Wall") include_directories ("${PROJECT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/libwds/rtsp/gen") add_library(wdscommon OBJECT logging.cpp message_handler.cpp rtsp_input_handler.cpp video_format.cpp) add_dependencies(wdscommon wdsrtsp) ================================================ FILE: libwds/common/logging.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2016 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/public/logging.h" namespace wds { static void Dummy(const char*, ...) {} LogSystem::LogFunction LogSystem::log_func_ = &Dummy; LogSystem::LogFunction LogSystem::vlog_func_ = &Dummy; LogSystem::LogFunction LogSystem::warning_func_ = &Dummy; LogSystem::LogFunction LogSystem::error_func_ = &Dummy; void LogSystem::set_log_func(LogFunction func) { log_func_ = func; } LogSystem::LogFunction LogSystem::log_func() { return log_func_; } void LogSystem::set_vlog_func(LogFunction func) { vlog_func_ = func; } LogSystem::LogFunction LogSystem::vlog_func() { return vlog_func_; } void LogSystem::set_warning_func(LogFunction func) { warning_func_ = func; } LogSystem::LogFunction LogSystem::warning_func() { return warning_func_; } void LogSystem::set_error_func(LogFunction func) { error_func_ = func; } LogSystem::LogFunction LogSystem::error_func() { return error_func_; } } // namespace wds ================================================ FILE: libwds/common/message_handler.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include "libwds/common/message_handler.h" #include "libwds/public/media_manager.h" namespace wds { using rtsp::Message; using rtsp::Request; using rtsp::Reply; bool MessageHandler::HandleTimeoutEvent(unsigned timer_id) const { return false; } MessageHandler::~MessageHandler() {} MessageSequenceHandler::MessageSequenceHandler(const InitParams& init_params) : MessageHandler(init_params), current_handler_(nullptr) { } MessageSequenceHandler::~MessageSequenceHandler() { } void MessageSequenceHandler::Start() { if (current_handler_) { return; } current_handler_ = handlers_.front(); current_handler_->Start(); } void MessageSequenceHandler::Reset() { if (current_handler_) { current_handler_->Reset(); current_handler_ = nullptr; } } bool MessageSequenceHandler::CanSend(Message* message) const { return current_handler_ && current_handler_->CanSend(message); } void MessageSequenceHandler::Send(std::unique_ptr message) { assert(current_handler_); current_handler_->Send(std::move(message)); } bool MessageSequenceHandler::CanHandle(Message* message) const { return current_handler_ && current_handler_->CanHandle(message); } void MessageSequenceHandler::Handle(std::unique_ptr message) { assert(current_handler_); current_handler_->Handle(std::move(message)); } void MessageSequenceHandler::AddSequencedHandler(MessageHandlerPtr handler) { assert(!current_handler_); // We are not started assert(handler); assert(handlers_.end() == std::find( handlers_.begin(), handlers_.end(), handler)); handlers_.push_back(handler); handler->set_observer(this); } void MessageSequenceHandler::OnCompleted(MessageHandlerPtr handler) { assert(handler == current_handler_); current_handler_->Reset(); auto it = std::find(handlers_.begin(), handlers_.end(), handler); assert(handlers_.end() != it); if (++it == handlers_.end()) { observer_->OnCompleted(shared_from_this()); return; } current_handler_ = *it; current_handler_->Start(); } void MessageSequenceHandler::OnError(MessageHandlerPtr handler) { assert(handler == current_handler_); handler->Reset(); observer_->OnError(shared_from_this()); } bool MessageSequenceHandler::HandleTimeoutEvent(unsigned timer_id) const { return current_handler_->HandleTimeoutEvent(timer_id); } MessageSequenceWithOptionalSetHandler::MessageSequenceWithOptionalSetHandler( const InitParams& init_params) : MessageSequenceHandler(init_params) { } MessageSequenceWithOptionalSetHandler::~MessageSequenceWithOptionalSetHandler() { } void MessageSequenceWithOptionalSetHandler::Start() { MessageSequenceHandler::Start(); for (MessageHandlerPtr handler : optional_handlers_) handler->Start(); } void MessageSequenceWithOptionalSetHandler::Reset() { MessageSequenceHandler::Reset(); for (MessageHandlerPtr handler : optional_handlers_) handler->Reset(); } bool MessageSequenceWithOptionalSetHandler::CanSend(Message* message) const { for (MessageHandlerPtr handler : optional_handlers_) if (handler->CanSend(message)) return true; if (MessageSequenceHandler::CanSend(message)) return true; return false; } void MessageSequenceWithOptionalSetHandler::Send(std::unique_ptr message) { for (MessageHandlerPtr handler : optional_handlers_) { if (handler->CanSend(message.get())) { handler->Send(std::move(message)); return; } } if (MessageSequenceHandler::CanSend(message.get())) { MessageSequenceHandler::Send(std::move(message)); return; } observer_->OnError(shared_from_this()); } bool MessageSequenceWithOptionalSetHandler::CanHandle(Message* message) const { if (MessageSequenceHandler::CanHandle(message)) return true; for (MessageHandlerPtr handler : optional_handlers_) if (handler->CanHandle(message)) return true; return false; } void MessageSequenceWithOptionalSetHandler::Handle(std::unique_ptr message) { if (MessageSequenceHandler::CanHandle(message.get())) { MessageSequenceHandler::Handle(std::move(message)); return; } for (MessageHandlerPtr handler : optional_handlers_) { if (handler->CanHandle(message.get())) { handler->Handle(std::move(message)); return; } } observer_->OnError(shared_from_this()); } void MessageSequenceWithOptionalSetHandler::AddOptionalHandler( MessageHandlerPtr handler) { assert(handler); assert(optional_handlers_.end() == std::find( optional_handlers_.begin(), optional_handlers_.end(), handler)); optional_handlers_.push_back(handler); handler->set_observer(this); } void MessageSequenceWithOptionalSetHandler::OnCompleted(MessageHandlerPtr handler) { auto it = std::find( optional_handlers_.begin(), optional_handlers_.end(), handler); if (it != optional_handlers_.end()) { handler->Reset(); handler->Start(); return; } MessageSequenceHandler::OnCompleted(handler); } void MessageSequenceWithOptionalSetHandler::OnError(MessageHandlerPtr handler) { handler->Reset(); observer_->OnError(shared_from_this()); } bool MessageSequenceWithOptionalSetHandler::HandleTimeoutEvent(unsigned timer_id) const { for (MessageHandlerPtr handler : optional_handlers_) if (handler->HandleTimeoutEvent(timer_id)) return true; return MessageSequenceHandler::HandleTimeoutEvent(timer_id); } // MessageReceiverBase MessageReceiverBase::MessageReceiverBase(const InitParams& init_params) : MessageHandler(init_params), wait_for_message_(false) {} MessageReceiverBase::~MessageReceiverBase() {} bool MessageReceiverBase::CanHandle(Message* message) const { assert(message); return wait_for_message_; } void MessageReceiverBase::Start() { wait_for_message_ = true; } void MessageReceiverBase::Reset() { wait_for_message_ = false; } bool MessageReceiverBase::CanSend(Message* message) const { return false; } void MessageReceiverBase::Send(std::unique_ptr message) {} void MessageReceiverBase::Handle(std::unique_ptr message) { assert(message); if (!CanHandle(message.get())) { observer_->OnError(shared_from_this()); return; } wait_for_message_ = false; std::unique_ptr reply = HandleMessage(message.get()); if (!reply) { observer_->OnError(shared_from_this()); return; } reply->header().set_cseq(message->cseq()); sender_->SendRTSPData(reply->ToString()); observer_->OnCompleted(shared_from_this()); } MessageSenderBase::MessageSenderBase(const InitParams& init_params) : MessageHandler(init_params) { } MessageSenderBase::~MessageSenderBase() { for (const ParcelData& data : parcel_queue_) sender_->ReleaseTimer(data.timer_id); } void MessageSenderBase::Reset() { while (!parcel_queue_.empty()) { sender_->ReleaseTimer(parcel_queue_.front().timer_id); parcel_queue_.pop_front(); } } void MessageSenderBase::Send(std::unique_ptr message) { assert(message); if (!CanSend(message.get())) { observer_->OnError(shared_from_this()); return; } parcel_queue_.push_back( {message->cseq(), sender_->CreateTimer(GetResponseTimeout())}); sender_->SendRTSPData(message->ToString()); } bool MessageSenderBase::CanHandle(Message* message) const { assert(message); return message->is_reply() && !parcel_queue_.empty() && (message->cseq() == parcel_queue_.front().cseq); } void MessageSenderBase::Handle(std::unique_ptr message) { assert(message); if (!CanHandle(message.get())) { observer_->OnError(shared_from_this()); return; } sender_->ReleaseTimer(parcel_queue_.front().timer_id); parcel_queue_.pop_front(); if (!HandleReply(static_cast(message.get()))) { observer_->OnError(shared_from_this()); return; } if (parcel_queue_.empty()) { observer_->OnCompleted(shared_from_this()); } } bool MessageSenderBase::HandleTimeoutEvent(unsigned timer_id) const { for (const ParcelData& data : parcel_queue_) if (data.timer_id == timer_id) return true; return false; } int MessageSenderBase::GetResponseTimeout() const { return kDefaultTimeoutValue; } SequencedMessageSender::SequencedMessageSender(const InitParams& init_params) : MessageSenderBase(init_params), to_be_send_(nullptr) { } SequencedMessageSender::~SequencedMessageSender() { } void SequencedMessageSender::Start() { auto message = CreateMessage(); to_be_send_ = message.get(); Send(std::move(message)); } void SequencedMessageSender::Reset() { to_be_send_ = nullptr; MessageSenderBase::Reset(); } bool SequencedMessageSender::CanSend(Message* message) const { return message && (message == to_be_send_); } } ================================================ FILE: libwds/common/message_handler.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_COMMON_MESSAGE_HANDLER_H_ #define LIBWDS_COMMON_MESSAGE_HANDLER_H_ #include #include #include #include #include #include "libwds/rtsp/message.h" #include "libwds/rtsp/reply.h" #include "libwds/public/logging.h" #include "libwds/public/peer.h" namespace wds { // Default keep-alive timer is 60 seconds const int kDefaultKeepAliveTimeout = 60; // Default timeout for RTSP message exchange const int kDefaultTimeoutValue = 5; class MediaManager; class MessageHandler; using MessageHandlerPtr = std::shared_ptr; inline MessageHandlerPtr make_ptr(MessageHandler* handler) { return MessageHandlerPtr(handler); } class MessageHandler : public std::enable_shared_from_this { public: class Observer { public: virtual void OnCompleted(MessageHandlerPtr handler) {} virtual void OnError(MessageHandlerPtr handler) {} protected: virtual ~Observer() {} }; struct InitParams { Peer::Delegate* sender; MediaManager* manager; Observer* observer; }; virtual ~MessageHandler(); virtual void Start() = 0; virtual void Reset() = 0; virtual bool CanSend(rtsp::Message* message) const = 0; virtual void Send(std::unique_ptr message) = 0; virtual bool CanHandle(rtsp::Message* message) const = 0; virtual void Handle(std::unique_ptr message) = 0; // For handlers that require timeout virtual bool HandleTimeoutEvent(unsigned timer_id) const; void set_observer(Observer* observer) { assert(observer); observer_ = observer; } protected: explicit MessageHandler(const InitParams& init_params) : sender_(init_params.sender), manager_(init_params.manager), observer_(init_params.observer) { assert(sender_); assert(manager_); assert(observer_); } Peer::Delegate* sender_; MediaManager* manager_; Observer* observer_; }; class MessageSequenceHandler : public MessageHandler, public MessageHandler::Observer { public: explicit MessageSequenceHandler(const InitParams& init_params); ~MessageSequenceHandler() override; void Start() override; void Reset() override; bool CanSend(rtsp::Message* message) const override; void Send(std::unique_ptr message) override; bool CanHandle(rtsp::Message* message) const override; void Handle(std::unique_ptr message) override; bool HandleTimeoutEvent(unsigned timer_id) const override; protected: void AddSequencedHandler(MessageHandlerPtr handler); // MessageHandler::Observer implementation. void OnCompleted(MessageHandlerPtr handler) override; void OnError(MessageHandlerPtr handler) override; std::vector handlers_; MessageHandlerPtr current_handler_; }; class MessageSequenceWithOptionalSetHandler : public MessageSequenceHandler { public: explicit MessageSequenceWithOptionalSetHandler(const InitParams& init_params); ~MessageSequenceWithOptionalSetHandler() override; void Start() override; void Reset() override; bool CanSend(rtsp::Message* message) const override; void Send(std::unique_ptr message) override; bool CanHandle(rtsp::Message* message) const override; void Handle(std::unique_ptr message) override; bool HandleTimeoutEvent(unsigned timer_id) const override; protected: void AddOptionalHandler(MessageHandlerPtr handler); // MessageHandler::Observer implementation. void OnCompleted(MessageHandlerPtr handler) override; void OnError(MessageHandlerPtr handler) override; std::vector optional_handlers_; }; // This is aux classes to handle single message. // There are two common scenarious: // 1. We send a message and wait for reply // class Handler : public MessageSender // // 2. We wait for the message and reply ourselves. // class Handler : public MessageReceiver class MessageReceiverBase : public MessageHandler { public: explicit MessageReceiverBase(const InitParams& init_params); ~MessageReceiverBase() override; protected: virtual std::unique_ptr HandleMessage(rtsp::Message* message) = 0; bool CanHandle(rtsp::Message* message) const override; void Handle(std::unique_ptr message) override; private: void Start() override; void Reset() override; bool CanSend(rtsp::Message* message) const override; void Send(std::unique_ptr message) override; bool wait_for_message_; }; template class MessageReceiver : public MessageReceiverBase { public: using MessageReceiverBase::MessageReceiverBase; protected: bool CanHandle(rtsp::Message* message) const override { return MessageReceiverBase::CanHandle(message) && message->is_request() && id == ToRequest(message)->id(); } }; class MessageSenderBase : public MessageHandler { public: explicit MessageSenderBase(const InitParams& init_params); ~MessageSenderBase() override; protected: virtual bool HandleReply(rtsp::Reply* reply) = 0; void Send(std::unique_ptr message) override; void Reset() override; bool HandleTimeoutEvent(unsigned timer_id) const override; private: bool CanHandle(rtsp::Message* message) const override; void Handle(std::unique_ptr message) override; virtual int GetResponseTimeout() const; struct ParcelData { int cseq; unsigned timer_id; }; std::list parcel_queue_; }; // To be used for optional senders. template class OptionalMessageSender : public MessageSenderBase { public: using MessageSenderBase::MessageSenderBase; protected: bool CanSend(rtsp::Message* message) const override { assert(message); return message->is_request() && ToRequest(message)->id() == id; } private: void Start() override {} }; // To be used for sequensed senders. class SequencedMessageSender : public MessageSenderBase { public: explicit SequencedMessageSender(const InitParams& init_params); ~SequencedMessageSender() override; protected: virtual std::unique_ptr CreateMessage() = 0; private: void Start() override; void Reset() override; bool CanSend(rtsp::Message* message) const override; rtsp::Message* to_be_send_; }; } // namespace wds #endif // LIBWDS_COMMON_MESSAGE_HANDLER_H_ ================================================ FILE: libwds/common/rtsp_input_handler.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "rtsp_input_handler.h" #include "libwds/rtsp/driver.h" #include "libwds/rtsp/message.h" #include namespace wds { using rtsp::Message; using rtsp::Driver; RTSPInputHandler::~RTSPInputHandler() { } void RTSPInputHandler::AddInput(const std::string& input) { rtsp_input_buffer_ += input; // First trying to get payload for the message obtained // from the previous input. if (message_ && !ParsePayload()) return; while (ParseHeader()) { if (!ParsePayload()) break; } } bool RTSPInputHandler::ParseHeader() { assert(!message_); static const char delimiter[] = "\r\n\r\n"; static const int delimiter_length = 4; size_t eom = rtsp_input_buffer_.find(delimiter); if (eom == std::string::npos) { return false; } const std::string& header = rtsp_input_buffer_.substr(0, eom + delimiter_length); rtsp_input_buffer_.erase(0, eom + delimiter_length); return Parse(header); } bool RTSPInputHandler::ParsePayload() { assert(message_); unsigned content_length = message_->header().content_length(); if (content_length == 0) { MessageParsed(std::move(message_)); return true; } if (rtsp_input_buffer_.size() < content_length) return false; const std::string& payload = rtsp_input_buffer_.substr(0, content_length); rtsp_input_buffer_.erase(0, content_length); if (!Parse(payload)) return false; MessageParsed(std::move(message_)); return true; } bool RTSPInputHandler::Parse(const std::string& input) { Driver::Parse(input, message_); if (!message_) { ParserErrorOccurred(rtsp_input_buffer_); rtsp_input_buffer_.clear(); return false; } return true; } } // namespace wds ================================================ FILE: libwds/common/rtsp_input_handler.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_COMMON_RTSP_INPUT_HANDLER_H_ #define LIBWDS_COMMON_RTSP_INPUT_HANDLER_H_ #include #include namespace wds { namespace rtsp { class Message; } // namespace rtsp // An aux class used to obtain Message object from the given raw input. class RTSPInputHandler { protected: RTSPInputHandler() = default; virtual ~RTSPInputHandler(); void AddInput(const std::string& input); // To be overridden. virtual void MessageParsed(std::unique_ptr message) = 0; virtual void ParserErrorOccurred(const std::string& invalid_input) {} private: bool ParseHeader(); bool ParsePayload(); bool Parse(const std::string& input); std::string rtsp_input_buffer_; std::unique_ptr message_; }; } #endif // LIBWDS_COMMON_RTSP_INPUT_HANDLER_H_ ================================================ FILE: libwds/common/video_format.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/public/media_manager.h" #include #include #include "libwds/public/logging.h" namespace wds { namespace { // Quality weight is calculated using following formula: // width * height * fps * 2 for progressive or 1 for interlaced frames struct QualityInfo { unsigned width; unsigned height; unsigned weight; }; const QualityInfo cea_info_table[] = { {640, 480, 640*480*60*2}, // CEA640x480p60 {720, 480, 720*480*60*2}, // CEA720x480p60 {720, 480, 720*480*60}, // CEA720x480i60 {720, 576, 720*576*50*2}, // CEA720x576p50 {720, 576, 720*576*50}, // CEA720x576i50 {1280, 720, 1280*720*30*2}, // CEA1280x720p30 {1280, 720, 1280*720*60*2}, // CEA1280x720p60 {1920, 1080, 1920*1080*30*2}, // CEA1920x1080p30 {1920, 1080, 1920*1080*60*2}, // CEA1920x1080p60 {1920, 1080, 1920*1080*60}, // CEA1920x1080i60 {1280, 720, 1280*720*25*2}, // CEA1280x720p25 {1280, 720, 1280*720*50*2}, // CEA1280x720p50 {1920, 1080, 1920*1080*25*2}, // CEA1920x1080p25 {1920, 1080, 1920*1080*50*2}, // CEA1920x1080p50 {1920, 1080, 1920*1080*50}, // CEA1920x1080i50 {1280, 720, 1280*720*24*2}, // CEA1280x720p24 {1920, 1080, 1920*1080*24*2} // CEA1920x1080p24 }; #define CEA_TABLE_LENGTH sizeof(cea_info_table) / sizeof(QualityInfo) const QualityInfo vesa_info_table[] = { {800, 600, 800*600*30*2}, // VESA800x600p30 {800, 600, 800*600*60*2}, // VESA800x600p60 {1024, 768, 1024*768*30*2}, // VESA1024x768p30 {1024, 768, 1024*768*60*2}, // VESA1024x768p60 {1152, 864, 1152*864*30*2}, // VESA1152x864p30 {1152, 864, 1152*864*60*2}, // VESA1152x864p60 {1280, 768, 1280*768*30*2}, // VESA1280x768p30 {1280, 768, 1280*768*60*2}, // VESA1280x768p60 {1280, 800, 1280*800*30*2}, // VESA1280x800p30 {1280, 800, 1280*800*60*2}, // VESA1280x800p60 {1360, 768, 1360*768*30*2}, // VESA1360x768p30 {1360, 768, 1360*768*60*2}, // VESA1360x768p60 {1366, 768, 1366*768*30*2}, // VESA1366x768p30 {1366, 768, 1366*768*60*2}, // VESA1366x768p60 {1280, 1024, 1280*1024*30*2}, // VESA1280x1024p30 {1280, 1024, 1280*1024*60*2}, // VESA1280x1024p60 {1400, 1050, 1400*1050*30*2}, // VESA1400x1050p30 {1400, 1050, 1400*1050*60*2}, // VESA1400x1050p60 {1440, 900, 1440*900*30*2}, // VESA1440x900p30 {1440, 900, 1440*900*60*2}, // VESA1440x900p60 {1600, 900, 1600*900*30*2}, // VESA1600x900p30 {1600, 900, 1600*900*60*2}, // VESA1600x900p60 {1600, 1200, 1600*1200*30*2}, // VESA1600x1200p30 {1600, 1200, 1600*1200*60*2}, // VESA1600x1200p60 {1680, 1024, 1680*1024*30*2}, // VESA1680x1024p30 {1680, 1024, 1680*1024*60*2}, // VESA1680x1024p60 {1680, 1050, 1680*1050*30*2}, // VESA1680x1050p30 {1680, 1050, 1680*1050*60*2}, // VESA1680x1050p60 {1920, 1200, 1920*1200*30*2} // VESA1920x1200p30 }; #define VESA_TABLE_LENGTH sizeof(vesa_info_table) / sizeof(QualityInfo) const QualityInfo hh_info_table[] = { {800, 480, 800*480*30*2}, // HH800x480p30 {800, 480, 800*480*60*2}, // HH800x480p60 {854, 480, 854*480*30*2}, // HH854x480p30 {854, 480, 854*480*60*2}, // HH854x480p60 {864, 480, 864*480*30*2}, // HH864x480p30 {864, 480, 864*480*60*2}, // HH864x480p60 {640, 360, 640*360*30*2}, // HH640x360p30 {640, 360, 640*360*60*2}, // HH640x360p60 {960, 540, 960*540*30*2}, // HH960x540p30 {960, 540, 960*540*60*2}, // HH960x540p60 {848, 480, 848*480*30*2}, // HH848x480p30 {848, 480, 848*480*60*2} // HH848x480p60 }; #define HH_TABLE_LENGTH sizeof(hh_info_table) / sizeof(QualityInfo) QualityInfo get_cea_info(const H264VideoFormat& format) { assert(format.rate_resolution < CEA_TABLE_LENGTH); return cea_info_table[format.rate_resolution]; } QualityInfo get_vesa_info(const H264VideoFormat& format) { assert(format.rate_resolution < VESA_TABLE_LENGTH); return vesa_info_table[format.rate_resolution]; } QualityInfo get_hh_info(const H264VideoFormat& format) { assert(format.rate_resolution < HH_TABLE_LENGTH); return hh_info_table[format.rate_resolution]; } QualityInfo get_quality_info(const H264VideoFormat& format) { QualityInfo info; switch (format.type) { case CEA: info = get_cea_info(format); break; case VESA: info = get_vesa_info(format); break; case HH: info = get_hh_info(format); break; default: assert(false); break; } return info; } std::pair get_resolution(const H264VideoFormat& format) { QualityInfo info = get_quality_info(format); return std::pair(info.width, info.height); } bool video_format_sort_func(const H264VideoFormat& a, const H264VideoFormat& b) { if (get_quality_info(a).weight != get_quality_info(b).weight) return get_quality_info(a).weight < get_quality_info(b).weight; if (a.profile != b.profile) return a.profile < b.profile; return a.level < b.level; } template void PopulateVideoFormatList( H264Profile profile, H264Level level, const RateAndResolutionsBitmap& bitmap, RREnum max_value, std::vector& formats) { if (bitmap.none()) return; for (RateAndResolution rr = 0; rr <= static_cast(max_value); ++rr) { if (bitmap.test(rr)) formats.push_back(H264VideoFormat(profile, level, static_cast(rr))); } } } // namespace void PopulateVideoFormatList( const H264VideoCodec& codec, std::vector& formats) { PopulateVideoFormatList( codec.profile, codec.level, codec.cea_rr, CEA1920x1080p24, formats); PopulateVideoFormatList( codec.profile, codec.level, codec.vesa_rr, VESA1920x1200p30, formats); PopulateVideoFormatList( codec.profile, codec.level, codec.hh_rr, HH848x480p60, formats); } H264VideoFormat FindOptimalVideoFormat( const NativeVideoFormat& native, const std::vector& local_codecs, const std::vector& remote_codecs, bool* success) { std::vector local_formats, remote_formats; for (const auto& codec : local_codecs) PopulateVideoFormatList(codec, local_formats); for (const auto& codec : remote_codecs) PopulateVideoFormatList(codec, remote_formats); std::sort(local_formats.begin(), local_formats.end(), video_format_sort_func); std::sort(remote_formats.begin(), remote_formats.end(), video_format_sort_func); auto it = local_formats.begin(); auto end = local_formats.end(); H264VideoFormat format; while(it != end) { auto match = std::find_if( remote_formats.begin(), remote_formats.end(), [&it] (const H264VideoFormat& format) { return ((*it).type == format.type) && (get_resolution(*it) == get_resolution(format)); }); if (match != remote_formats.end()) { format = *match; break; } ++it; } // Should not happen, 640x480p60 should be always supported! if (it == end) { WDS_ERROR("Failed to find compatible video format."); if (success) *success = false; return format; } // if remote device supports higher codec profile / level // downgrade them to what we support locally. if (format.profile > (*it).profile) format.profile = (*it).profile; if (format.level > (*it).level) format.level = (*it).level; if (success) *success = true; return format; } } // namespace wds ================================================ FILE: libwds/public/audio_codec.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_PUBLIC_AUDIO_CODEC_H_ #define LIBWDS_PUBLIC_AUDIO_CODEC_H_ #include namespace wds { enum AudioFormats { LPCM, AAC, AC3 }; enum LPCMModes { LPCM_44_1K_16B_2CH, LPCM_48K_16B_2CH }; enum AACModes { AAC_48K_16B_2CH, AAC_48K_16B_4CH, AAC_48K_16B_6CH, AAC_48K_16B_8CH }; enum AC3Modes { AC3_48K_16B_2CH, AC3_48K_16B_4CH, AC3_48K_16B_6CH }; using AudioModes = std::bitset<32>; /** * @brief The AudioCodec struct * * Repersents a tuple used in 'wfd-audio-codecs'. */ struct AudioCodec { AudioCodec() : format(LPCM), modes(AudioModes().set(LPCM_48K_16B_2CH)), latency(0) {} AudioCodec(AudioFormats format, const AudioModes& modes, unsigned latency) : format(format), modes(modes), latency(latency) {} AudioFormats format; AudioModes modes; unsigned latency; }; } // namespace wds #endif // LIBWDS_PUBLIC_AUDIO_CODEC_H_ ================================================ FILE: libwds/public/connector_type.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_PUBLIC_CONNECTOR_TYPE_H_ #define LIBWDS_PUBLIC_CONNECTOR_TYPE_H_ namespace wds { enum ConnectorType { ConnectorTypeVGA = 0, // TODO : Add the rest of connector types. ConnectorTypeUndefined = 255, ConnectorTypeNone }; } // namespace wds #endif // LIBWDS_PUBLIC_CONNECTOR_TYPE_H_ ================================================ FILE: libwds/public/logging.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_PUBLIC_LOGGING_H_ #define LIBWDS_PUBLIC_LOGGING_H_ #include #include "wds_export.h" namespace wds { /** * WFD logging subsystem. */ class WDS_EXPORT LogSystem { public: typedef void (*LogFunction)(const char*, ...); /** * Sets a function to log a normal message. * @param function to log a normal message */ static void set_log_func(LogFunction func); /** * Gets a function to log a normal message @see set_log_func * @return function to log a normal message */ static LogFunction log_func(); /** * Sets a function to log a verbose message. * @param function to log a verbose message */ static void set_vlog_func(LogFunction func); /** * Gets a function to log a verbose message @see set_vlog_func * @return function to log a verbose message */ static LogFunction vlog_func(); /** * Sets a function to log a warning message. * @param function to log a warning message */ static void set_warning_func(LogFunction func); /** * Gets a function to log a warning message @see set_warning_func * @return function to log a warning message */ static LogFunction warning_func(); /** * Sets a function to log an error message. * @param function to log an error message */ static void set_error_func(LogFunction func); /** * Gets a function to log an error message @see set_error_func * @return function to log an error message */ static LogFunction error_func(); private: static LogFunction log_func_; static LogFunction vlog_func_; static LogFunction warning_func_; static LogFunction error_func_; private: LogSystem() = delete; }; } #define WDS_LOG(...) (*wds::LogSystem::log_func())(__VA_ARGS__); #define WDS_VLOG(...) (*wds::LogSystem::vlog_func())(__VA_ARGS__); #define WDS_WARNING(...) (*wds::LogSystem::warning_func())(__VA_ARGS__); #define WDS_ERROR(...) (*wds::LogSystem::error_func())(__VA_ARGS__); #endif // LIBWDS_PUBLIC_LOGGING_H_ ================================================ FILE: libwds/public/media_manager.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_PUBLIC_MEDIA_MANAGER_H_ #define LIBWDS_PUBLIC_MEDIA_MANAGER_H_ #include #include #include "audio_codec.h" #include "connector_type.h" #include "video_format.h" #include "wds_export.h" namespace wds { enum SessionType { AudioSession = 1, // Audio only session VideoSession = 1 << 1, // Video only session AudioVideoSession = AudioSession | VideoSession // Audio/video session }; /** * MediaManager interface. * * MediaManager instance is used by the state machine to control media stream * during WFD session. * * MediaManager contains the common methods for both WFD sink and WFD source. * The client applications are not supposed to implement it directly, they should * rather implement either @c SinkMediaManager or @c SourceMediaManager. * @see SinkMediaManager, SourceMediaManager */ class MediaManager { public: virtual ~MediaManager() {} /** * Triggers playback of the media stream. */ virtual void Play() = 0; /** * Pauses playback of the media stream. */ virtual void Pause() = 0; /** * Destroys media stream. */ virtual void Teardown() = 0; /** * Queries whether media stream is paused. * @return true if media stream is paused, false otherwise. */ virtual bool IsPaused() const = 0; /** * Returns unique WFD session id. * * The session Id is generated by WFD source. * * @return unique id for WFD session */ virtual std::string GetSessionId() const = 0; }; /** * SinkMediaManager interface. * * Extends the common @c MediaManager interface with WFD sink specific methods. * @see MediaManager */ class SinkMediaManager : public MediaManager { public: ~SinkMediaManager() override { } /** * Returns RTP listening ports that are used by WFD sink to receive media streams. * * In case of coupled sink configuration video and audio data could be sent * to different RTP ports. * * @return pair of RTP ports, port0 and port1 */ virtual std::pair GetLocalRtpPorts() const = 0; /** * Sets presentation URL for media stream. * Presentation URL can be referred in order to control media stream resource * within WFD session. * * The implementation must store the given value and return it at GetPresentationUrl. * * @param presentation URL that represents video / audio stream */ virtual void SetPresentationUrl(const std::string& url) = 0; /** * Returns presentation URL for managed media resource. * @see SetPresentationUrl * @return presentation URL */ virtual std::string GetPresentationUrl() const = 0; /** * Sets unique ID for WFD session. * * The implementation must store the given value and return it at GetSessionId. * * @param string that uniquely identifies WFD session */ virtual void SetSessionId(const std::string& session) = 0; /** * Returns list of supported H264 video formats * @return vector of supported H264 video formats */ virtual std::vector GetSupportedH264VideoCodecs() const = 0; /** * Returns native video format of a device * @return native video format */ virtual NativeVideoFormat GetNativeVideoFormat() const = 0; /** * Sets optimal H264 format that would be used to send / receive video stream * * @param optimal H264 format * @return true if format can be used by media manager, false otherwise */ virtual bool SetOptimalVideoFormat(const H264VideoFormat& optimal_format) = 0; /** * Returns active connector type of a device * @return connector type. @see ConnectorType */ virtual ConnectorType GetConnectorType() const = 0; }; /** * SourceMediaManager interface. * * Extends the common @c MediaManager interface with WFD source specific methods. * @see MediaManager */ class SourceMediaManager : public MediaManager { public: ~SourceMediaManager() override { } /** * Returns media type for the current session. * @see MediaType * @return media time. */ virtual SessionType GetSessionType() const = 0; /** * Sets RTP ports used by WFD sink to receive media streams. * * In case of coupled sink configuration video and audio data could be sent * to different RTP ports. * * WFD source must use these RTP ports for outgoing UDP connection. * * The implementation must store the given values and return them at GetSinkRtpPorts. * * @param port0 RTP port for video / audio stream * @param port1 RTP port that could be used to send audio stream */ virtual void SetSinkRtpPorts(int port1, int port2) = 0; /** * Returns RTP ports that are used by WFD sink to receive media streams. * @see SetRtpPorts * @return pair of RTP ports, port0 and port1 */ virtual std::pair GetSinkRtpPorts() const = 0; /** * Returns the local WFD source RTP port transmitting the media stream. * @return RTP port */ virtual int GetLocalRtpPort() const = 0; /** * Initializes optimal video format * The optimal video format will be returned by GetOptimalVideoFormat * * @param sink_native_format format of the sink device * @param sink_supported_formats of H264 formats that are supported by the sink device * @return true if optimal video format is successfully initialized, false otherwise */ virtual bool InitOptimalVideoFormat( const NativeVideoFormat& sink_native_format, const std::vector& sink_supported_codecs) = 0; /** * Gets optimal H264 format @see InitOptimalVideoFormat * * @return optimal H264 format */ virtual H264VideoFormat GetOptimalVideoFormat() const = 0; /** * Initializes optimal audio codec * The optimal audio codec will be returned by GetOptimalAudioFormat * * @param sink_supported_codecs list of the codecs supported by sink * @return true if optimal audio codec is successfully initialized, false otherwise */ virtual bool InitOptimalAudioFormat(const std::vector& sink_supported_codecs) = 0; /** * Gets optimal audio codec @see InitOptimalAudioFormat * * @return optimal audio codec */ virtual AudioCodec GetOptimalAudioFormat() const = 0; /** * Sends of H.264 instantaneous decoding refresh (IDR) picture * to recover the content streaming. */ virtual void SendIDRPicture() = 0; }; inline SourceMediaManager* ToSourceMediaManager(MediaManager* mng) { return static_cast(mng); } inline SinkMediaManager* ToSinkMediaManager(MediaManager* mng) { return static_cast(mng); } } // namespace wds #endif // LIBWDS_PUBLIC_MEDIA_MANAGER_H_ ================================================ FILE: libwds/public/peer.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_PUBLIC_PEER_H_ #define LIBWDS_PUBLIC_PEER_H_ #include #include "wds_export.h" namespace wds { enum ErrorType { /// Arrived message cannot be handled by the state machine at the time. UnexpectedMessageError, /// RTSP message cannot be created form the given input. MessageParseError, /// The connected peer became unresponsive. TimeoutError }; /** * Peer interface. * * Peer is a base class for sink and source state machines. */ class WDS_EXPORT Peer { public: /** * Delegate interface. * * Implementation of Delegate interface is used by the state machine * to obtain necessary context from the client. */ class Delegate { public: /** * The implementation should send the RTSP data over the network * @param data data to be send */ virtual void SendRTSPData(const std::string& data) = 0; /** * Returns the local IP address * @return IP address */ virtual std::string GetLocalIPAddress() const = 0; /** * The implementation should start a timer to be used by the state machine. * @param seconds the time interval in seconds * @return unique timer id within the session */ virtual unsigned CreateTimer(int seconds) = 0; /** * The implementation should release timer by the given id. * @param timer_id id of the timer to be released. */ virtual void ReleaseTimer(unsigned timer_id) = 0; /** * Returns the sequence number for the following RTSP request-response pair * @param initial_peer_cseq is provided for the WFD sink implementation at * the first method's call during the WFD session and it contains the * initial request sequence number obtained from the WFD source (the initial * sequence numbers of connected peers may not be identical). */ virtual int GetNextCSeq(int* initial_peer_cseq = nullptr) const = 0; protected: virtual ~Delegate() {} }; /** * Observer interface. * * This interface can be used by the client in order to get notifications * from the state machine. */ class Observer { public: /** * This method is called by the state machine if an error has occurred. * State machine is not reset. * * @param error type of the error * * @see ErrorType */ virtual void ErrorOccurred(ErrorType error) {} /** * This method is called by the state machine if the session has been * completed normally (with 'teardown' message). * State machine is not reset. */ virtual void SessionCompleted() {} protected: virtual ~Observer() {} }; virtual ~Peer() {} /** * Starts wds state machine (source or sink) */ virtual void Start() = 0; /** * Reset wds state machine (source or sink) to the initial state. */ virtual void Reset() = 0; /** * Whenever RTSP data is received, this method should be called, so that * the state machine could take action based on current state. */ virtual void RTSPDataReceived(const std::string& data) = 0; // Following methods: // @see Teardown() // @see Play() // @see Pause() // send M5 wfd_trigger_method messages for Peers that implement // Source functionality or M7, M8 and M9 for Sink implementations /** * Sends RTSP teardown request. * @return true if request can be sent, false otherwise. */ virtual bool Teardown() = 0; /** * Sends RTSP play request. * @return true if request can be sent, false otherwise. */ virtual bool Play() = 0; /** * Sends RTSP pause request. * @return true if request can be sent, false otherwise. */ virtual bool Pause() = 0; /** * This method should be called by the client to notify the state * machine about the timer events. * @param timer_id id of the timer * @return true if request can be sent, false otherwise. * * @see Delegate::CreateTimer() */ virtual void OnTimerEvent(unsigned timer_id) = 0; }; } #endif // LIBWDS_PUBLIC_PEER_H_ ================================================ FILE: libwds/public/sink.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_PUBLIC_SINK_H_ #define LIBWDS_PUBLIC_SINK_H_ #include "peer.h" namespace wds { class SinkMediaManager; /** * Sink state machine implementation */ class WDS_EXPORT Sink : public Peer { public: virtual ~Sink() {} /** * Factory method that creates Sink state machine. * @param delegate that is used for networking * @param media manger that is used for media stream management * @return newly created Sink instance */ static Sink* Create(Peer::Delegate* delegate, SinkMediaManager* mng); }; } #endif // LIBWDS_PUBLIC_SINK_H_ ================================================ FILE: libwds/public/source.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_PUBLIC_SOURCE_H_ #define LIBWDS_PUBLIC_SOURCE_H_ #include "peer.h" namespace wds { class SourceMediaManager; /** * Source state machine implementation */ class WDS_EXPORT Source : public Peer { public: /** * Factory method that creates Source state machine. * @param delegate that is used for networking * @param media manger that is used for media stream management * @param observer * @return newly created Source instance */ static Source* Create(Peer::Delegate* delegate, SourceMediaManager* mng, Peer::Observer* observer = nullptr); }; } #endif // LIBWDS_PUBLIC_SOURCE_H_ ================================================ FILE: libwds/public/video_format.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_PUBLIC_VIDEO_FORMAT_H_ #define LIBWDS_PUBLIC_VIDEO_FORMAT_H_ #include #include #include "wds_export.h" namespace wds { using RateAndResolution = unsigned; using RateAndResolutionsBitmap = std::bitset<32>; // NOTE : Do not change the elements order in the following enums! enum ResolutionType { CEA, VESA, HH }; enum CEARatesAndResolutions { CEA640x480p60, CEA720x480p60, CEA720x480i60, CEA720x576p50, CEA720x576i50, CEA1280x720p30, CEA1280x720p60, CEA1920x1080p30, CEA1920x1080p60, CEA1920x1080i60, CEA1280x720p25, CEA1280x720p50, CEA1920x1080p25, CEA1920x1080p50, CEA1920x1080i50, CEA1280x720p24, CEA1920x1080p24 }; enum VESARatesAndResolutions { VESA800x600p30, VESA800x600p60, VESA1024x768p30, VESA1024x768p60, VESA1152x864p30, VESA1152x864p60, VESA1280x768p30, VESA1280x768p60, VESA1280x800p30, VESA1280x800p60, VESA1360x768p30, VESA1360x768p60, VESA1366x768p30, VESA1366x768p60, VESA1280x1024p30, VESA1280x1024p60, VESA1400x1050p30, VESA1400x1050p60, VESA1440x900p30, VESA1440x900p60, VESA1600x900p30, VESA1600x900p60, VESA1600x1200p30, VESA1600x1200p60, VESA1680x1024p30, VESA1680x1024p60, VESA1680x1050p30, VESA1680x1050p60, VESA1920x1200p30 }; enum HHRatesAndResolutions { HH800x480p30, HH800x480p60, HH854x480p30, HH854x480p60, HH864x480p30, HH864x480p60, HH640x360p30, HH640x360p60, HH960x540p30, HH960x540p60, HH848x480p30, HH848x480p60 }; enum H264Profile { CBP, CHP }; enum H264Level { k3_1, k3_2, k4, k4_1, k4_2 }; struct NativeVideoFormat { NativeVideoFormat() : type(CEA), rate_resolution(CEA640x480p60) {} NativeVideoFormat(CEARatesAndResolutions rr) : type(CEA), rate_resolution(rr) {} NativeVideoFormat(VESARatesAndResolutions rr) : type(VESA), rate_resolution(rr) {} NativeVideoFormat(HHRatesAndResolutions rr) : type(HH), rate_resolution(rr) {} ResolutionType type; RateAndResolution rate_resolution; }; /** * A single video format that the source selects for streaming. * * H264VideoFormat is a H264 profile, H264 level, and a single CEA, * VESA or HH resolution. Sources are choosing the video format by matching what they * support to what the sink supports, and then they communicate the chosen format back * to the sink. */ struct H264VideoFormat { H264VideoFormat() : profile(CBP), level(k3_1), type(CEA), rate_resolution(CEA640x480p60) {} H264VideoFormat(H264Profile profile, H264Level level, CEARatesAndResolutions rr) : profile(profile), level(level), type(CEA), rate_resolution(rr) {} H264VideoFormat(H264Profile profile, H264Level level, VESARatesAndResolutions rr) : profile(profile), level(level), type(VESA), rate_resolution(rr) {} H264VideoFormat(H264Profile profile, H264Level level, HHRatesAndResolutions rr) : profile(profile), level(level), type(HH), rate_resolution(rr) {} H264Profile profile; H264Level level; ResolutionType type; RateAndResolution rate_resolution; }; /** * Represents tuple used in 'wfd-video-formats'. * * H264VideoCodec is a H264 profile, H264 level, and three sets of * CEA, VESA and HH resolutions. Sinks send one or several H264VideoCodec * to sources (for example because supported resolutions might * be different for CBP and CHP). */ struct H264VideoCodec { H264VideoCodec() : profile(CBP), level(k3_1), cea_rr(RateAndResolutionsBitmap().set(CEA640x480p60)) {} H264VideoCodec(H264Profile profile, H264Level level, const RateAndResolutionsBitmap& cea, const RateAndResolutionsBitmap& vesa, const RateAndResolutionsBitmap& hh) : profile(profile), level(level), cea_rr(cea), vesa_rr(vesa), hh_rr(hh) {} H264Profile profile; H264Level level; RateAndResolutionsBitmap cea_rr; RateAndResolutionsBitmap vesa_rr; RateAndResolutionsBitmap hh_rr; }; /** * An auxiliary function which populates list of @c H264VideoFormat * items from the given @c H264VideoCodec instance. * * @param codec the given @c H264VideoCodec instance. * @param formats resulting list of @c H264VideoFormat items */ WDS_EXPORT void PopulateVideoFormatList( const H264VideoCodec& codec, std::vector& formats); /** * An auxiliary function to find the optimal format for streaming. * The quality selection algorithm will pick codec with higher bandwidth. * * @param native format of a remote device * @param local_codecs list of H264 codecs that are supported by local device * @param remote_codecs list of H264 codecs that are supported by remote device * @return optimal H264 video format */ WDS_EXPORT H264VideoFormat FindOptimalVideoFormat( const NativeVideoFormat& remote_native_format, const std::vector& local_codecs, const std::vector& remote_codecs, bool* success = nullptr); } // namespace wds #endif // LIBWDS_PUBLIC_VIDEO_FORMAT_H_ ================================================ FILE: libwds/public/wds_export.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_PUBLIC_WDS_EXPORT_H_ #define LIBWDS_PUBLIC_WDS_EXPORT_H_ #if defined _WIN32 || defined _WIN64 #define WDS_EXPORT __declspec(dllexport) #else #define WDS_EXPORT __attribute__((visibility("default"))) #endif #endif // LIBWDS_PUBLIC_WDS_EXPORT_H_ ================================================ FILE: libwds/rtsp/CMakeLists.txt ================================================ #FIXME in the future: with cmake 2.8.12 and up it's better #to use target_compile_options or add_compile_options set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fvisibility=hidden -fPIC") set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -std=c99 -Wall") # Make directory for generated parser files set(PARSER_GEN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gen") file(MAKE_DIRECTORY ${PARSER_GEN_DIR}) include_directories ("${PROJECT_SOURCE_DIR}" "${PARSER_GEN_DIR}" ) if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(PARSER_DEBUG_OPTIONS "--debug -v") endif (CMAKE_BUILD_TYPE STREQUAL "Debug") find_package(BISON REQUIRED) BISON_TARGET(Parser parser.ypp ${PARSER_GEN_DIR}/parser.cpp COMPILE_FLAGS "-l -p wds_ ${PARSER_DEBUG_OPTIONS}") find_package(FLEX REQUIRED) FLEX_TARGET(MessageLexer messagelexer.l ${PARSER_GEN_DIR}/messagescanner.cpp COMPILE_FLAGS "-L -P message_ ${PARSER_DEBUG_OPTIONS}") ADD_FLEX_BISON_DEPENDENCY(MessageLexer Parser) FLEX_TARGET(HeaderLexer headerlexer.l ${PARSER_GEN_DIR}/headerscanner.cpp COMPILE_FLAGS "-L -P header_ ${PARSER_DEBUG_OPTIONS}") ADD_FLEX_BISON_DEPENDENCY(HeaderLexer Parser) FLEX_TARGET(ErrorLexer errorlexer.l ${PARSER_GEN_DIR}/errorscanner.cpp COMPILE_FLAGS "-L -P error_ ${PARSER_DEBUG_OPTIONS}") ADD_FLEX_BISON_DEPENDENCY(ErrorLexer Parser) add_library(wdsrtsp OBJECT ${BISON_Parser_OUTPUT_SOURCE} ${FLEX_MessageLexer_OUTPUTS} ${FLEX_ErrorLexer_OUTPUTS} ${FLEX_HeaderLexer_OUTPUTS} driver.cpp message.cpp header.cpp transportheader.cpp payload.cpp options.cpp reply.cpp getparameter.cpp setparameter.cpp play.cpp pause.cpp teardown.cpp setup.cpp property.cpp genericproperty.cpp formats3d.cpp audiocodecs.cpp clientrtpports.cpp contentprotection.cpp coupledsink.cpp displayedid.cpp presentationurl.cpp route.cpp triggermethod.cpp videoformats.cpp i2c.cpp avformatchangetiming.cpp uibcsetting.cpp standbyresumecapability.cpp standby.cpp idrrequest.cpp connectortype.cpp preferreddisplaymode.cpp uibccapability.cpp propertyerrors.cpp ) ================================================ FILE: libwds/rtsp/audiocodecs.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/audiocodecs.h" #include #include "libwds/rtsp/macros.h" namespace wds { namespace rtsp { namespace { std::string ToString(const wds::AudioCodec& codec) { MAKE_HEX_STRING_8(audio_modes_str, static_cast(codec.modes.to_ulong())); MAKE_HEX_STRING_2(latency_str, codec.latency); const char* const name[] = {"LPCM", "AAC", "AC3"}; std::string ret = name[codec.format] + std::string(SPACE) + audio_modes_str + std::string(SPACE) + latency_str; return ret; } } AudioCodecs::AudioCodecs() : Property(AudioCodecsPropertyType, true) { } AudioCodecs::AudioCodecs(const std::vector& audio_codecs) : Property(AudioCodecsPropertyType), audio_codecs_(audio_codecs) { } AudioCodecs::~AudioCodecs() { } std::string AudioCodecs::ToString() const { std::string ret = PropertyName::wfd_audio_codecs + std::string(SEMICOLON) + std::string(SPACE); if (audio_codecs_.empty()) return ret + NONE; auto it = audio_codecs_.begin(); auto end = audio_codecs_.end(); while (it != end) { ret += wds::rtsp::ToString(*it); ++it; if (it != end) ret += ", "; } return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/audiocodecs.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_AUDIOCODECS_H_ #define LIBWDS_RTSP_AUDIOCODECS_H_ #include #include "libwds/public/audio_codec.h" #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class AudioCodecs: public Property { public: AudioCodecs(); AudioCodecs(const std::vector& audio_codecs); ~AudioCodecs() override; const std::vector& audio_codecs() const { return audio_codecs_; } std::string ToString() const override; private: std::vector audio_codecs_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_AUDIOCODECS_H_ ================================================ FILE: libwds/rtsp/avformatchangetiming.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/avformatchangetiming.h" #include "libwds/rtsp/macros.h" namespace wds { namespace rtsp { AVFormatChangeTiming::AVFormatChangeTiming(unsigned long long int pts, unsigned long long int dts) : Property(AVFormatChangeTimingPropertyType), pts_(pts), dts_(dts) { } AVFormatChangeTiming::~AVFormatChangeTiming() { } std::string AVFormatChangeTiming::ToString() const { MAKE_HEX_STRING_10(pts, pts_); MAKE_HEX_STRING_10(dts, dts_); std::string ret = PropertyName::wfd_av_format_change_timing + std::string(SEMICOLON) + std::string(SPACE) + pts + std::string(SPACE) + dts; return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/avformatchangetiming.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_AVFORMATCHANGETIMING_H_ #define LIBWDS_RTSP_AVFORMATCHANGETIMING_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class AVFormatChangeTiming: public Property { public: AVFormatChangeTiming(unsigned long long int pts, unsigned long long int dts); ~AVFormatChangeTiming() override; unsigned long long int pts() const { return pts_; } unsigned long long int dts() const { return dts_; } std::string ToString() const override; private: unsigned long long int pts_; unsigned long long int dts_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_AVFORMATCHANGETIMING_H_ ================================================ FILE: libwds/rtsp/clientrtpports.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/clientrtpports.h" namespace wds { namespace rtsp { namespace { const char profile[] = "RTP/AVP/UDP;unicast"; const char mode[] = "mode=play"; } ClientRtpPorts::ClientRtpPorts(unsigned short rtp_port_0, unsigned short rtp_port_1) : Property(ClientRTPPortsPropertyType), rtp_port_0_(rtp_port_0), rtp_port_1_(rtp_port_1) { } ClientRtpPorts::~ClientRtpPorts() { } std::string ClientRtpPorts::ToString() const { return PropertyName::wfd_client_rtp_ports + std::string(SEMICOLON) + std::string(SPACE) + profile + std::string(SPACE) + std::to_string(rtp_port_0_) + std::string(SPACE) + std::to_string(rtp_port_1_) + std::string(SPACE) + mode; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/clientrtpports.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_CLIENTRTPPORTS_H_ #define LIBWDS_RTSP_CLIENTRTPPORTS_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class ClientRtpPorts: public Property { public: ClientRtpPorts(unsigned short rtp_port_0, unsigned short rtp_port_1); ~ClientRtpPorts() override; unsigned short rtp_port_0() const { return rtp_port_0_; } unsigned short rtp_port_1() const { return rtp_port_1_; } std::string ToString() const override; private: unsigned short rtp_port_0_; unsigned short rtp_port_1_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_CLIENTRTPPORTS_H_ ================================================ FILE: libwds/rtsp/connectortype.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/connectortype.h" #include "libwds/rtsp/macros.h" namespace wds { namespace rtsp { ConnectorType::ConnectorType() : Property(ConnectorTypePropertyType, true), connector_type_() { } ConnectorType::ConnectorType(unsigned char connector_type) : Property(ConnectorTypePropertyType), connector_type_(connector_type) { } ConnectorType::ConnectorType(wds::ConnectorType connector_type) : Property(ConnectorTypePropertyType, connector_type == wds::ConnectorTypeNone) { connector_type_ = is_none() ? 0 // Ignored. : static_cast(connector_type); } ConnectorType::~ConnectorType() { } std::string ConnectorType::ToString() const { std::string ret = PropertyName::wfd_connector_type + std::string(SEMICOLON) + std::string(SPACE); if (is_none()) { ret += NONE; } else { MAKE_HEX_STRING_2(connector_type, connector_type_); ret += connector_type; } return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/connectortype.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_CONNECTORTYPE_H_ #define LIBWDS_RTSP_CONNECTORTYPE_H_ #include "libwds/public/connector_type.h" #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class ConnectorType: public Property { public: ConnectorType(); explicit ConnectorType(unsigned char connector_type); explicit ConnectorType(wds::ConnectorType connector_type); ~ConnectorType() override; unsigned char connector_type() const { return connector_type_; } std::string ToString() const override; private: unsigned char connector_type_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_CONNECTORTYPE_H_ ================================================ FILE: libwds/rtsp/constants.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_CONSTANTS_H_ #define LIBWDS_RTSP_CONSTANTS_H_ namespace wds { namespace rtsp { const char SEMICOLON[] = ":"; const char SPACE[] = " "; const char NONE[] = "none"; const char CRLF[] = "\r\n"; const char RTSP_END[] = "RTSP/1.0"; enum PropertyType { AVFormatChangeTimingPropertyType, AudioCodecsPropertyType, ClientRTPPortsPropertyType, ConnectorTypePropertyType, ContentProtectionPropertyType, CoupledSinkPropertyType, DisplayEdidPropertyType, GenericPropertyType, I2CPropertyType, IDRRequestPropertyType, PreferredDisplayModePropertyType, PresentationURLPropertyType, RoutePropertyType, StandbyPropertyType, StandbyResumeCapabilityPropertyType, TriggerMethodPropertyType, UIBCCapabilityPropertyType, UIBCSettingPropertyType, Video3DFormatsPropertyType, VideoFormatsPropertyType }; namespace PropertyName { const char wfd_audio_codecs[] = "wfd_audio_codecs"; const char wfd_video_formats[] = "wfd_video_formats"; const char wfd_3d_video_formats[] = "wfd_3d_video_formats"; const char wfd_content_protection[] = "wfd_content_protection"; const char wfd_display_edid[] = "wfd_display_edid"; const char wfd_coupled_sink[] = "wfd_coupled_sink"; const char wfd_trigger_method[] = "wfd_trigger_method"; const char wfd_presentation_url[] = "wfd_presentation_URL"; const char wfd_client_rtp_ports[] = "wfd_client_rtp_ports"; const char wfd_route[] = "wfd_route"; const char wfd_I2C[] = "wfd_I2C"; const char wfd_av_format_change_timing[] = "wfd_av_format_change_timing"; const char wfd_preferred_display_mode[] = "wfd_preferred_display_mode"; const char wfd_uibc_capability[] = "wfd_uibc_capability"; const char wfd_uibc_setting[] = "wfd_uibc_setting"; const char wfd_standby_resume_capability[] = "wfd_standby_resume_capability"; const char wfd_standby[] = "wfd_standby"; const char wfd_connector_type[] = "wfd_connector_type"; const char wfd_idr_request[] = "wfd_idr_request"; } // namespace PropertyName enum Method { OPTIONS, SET_PARAMETER, GET_PARAMETER, SETUP, PLAY, TEARDOWN, PAUSE, ORG_WFA_WFD_1_0 }; namespace MethodName { const char OPTIONS[] = "OPTIONS"; const char SET_PARAMETER[] = "SET_PARAMETER"; const char GET_PARAMETER[] = "GET_PARAMETER"; const char SETUP[] = "SETUP"; const char PLAY[] = "PLAY"; const char TEARDOWN[] = "TEARDOWN"; const char PAUSE[] = "PAUSE"; const char ORG_WFA_WFD1_0[] = "org.wfa.wfd1.0"; const char* const name[] = { OPTIONS, SET_PARAMETER, GET_PARAMETER, SETUP, PLAY, TEARDOWN, PAUSE, ORG_WFA_WFD1_0 }; } enum RTSPStatusCode { STATUS_OK = 200, STATUS_SeeOther = 303, STATUS_NotAcceptable = 406, STATUS_UnsupportedMediaType = 415, STATUS_NotImplemented = 501 }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_CONSTANTS_H_ ================================================ FILE: libwds/rtsp/contentprotection.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/contentprotection.h" #include namespace wds { namespace rtsp { namespace { const char* name[] = {"HDCP2.0", "HDCP2.1"}; const char port_prefix[] = "port="; } ContentProtection::ContentProtection(HDCPSpec hdcp_spec, unsigned int port) : Property (ContentProtectionPropertyType), hdcp_spec_(hdcp_spec), port_(port) { } ContentProtection::ContentProtection(): Property (ContentProtectionPropertyType, true) { } ContentProtection::~ContentProtection() { } ContentProtection::HDCPSpec ContentProtection::hdcp_spec() const { assert(hdcp_spec_ != HDCP_SPEC_2_0 || hdcp_spec_ != HDCP_SPEC_2_1); return hdcp_spec_; } std::string ContentProtection::ToString() const { std::string ret = PropertyName::wfd_content_protection + std::string(SEMICOLON) + std::string(SPACE); if (is_none()) ret += NONE; else ret += name[hdcp_spec()] + std::string(SPACE) + port_prefix + std::to_string(port_); return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/contentprotection.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_CONTENTPROTECTION_H_ #define LIBWDS_RTSP_CONTENTPROTECTION_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class ContentProtection: public Property { public: enum HDCPSpec { HDCP_SPEC_2_0, HDCP_SPEC_2_1 }; public: ContentProtection(); ContentProtection(HDCPSpec hdcp_spec, unsigned int port); ~ContentProtection() override; HDCPSpec hdcp_spec() const; unsigned int port() const { return port_; } std::string ToString() const override; private: HDCPSpec hdcp_spec_; unsigned int port_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_CONTENTPROTECTION_H_ ================================================ FILE: libwds/rtsp/coupledsink.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/coupledsink.h" #include #include "libwds/rtsp/macros.h" namespace wds { namespace rtsp { CoupledSink::CoupledSink(unsigned char status, unsigned long long int sink_address) : Property(CoupledSinkPropertyType), status_(status), sink_address_(sink_address) { } CoupledSink::CoupledSink(): Property(CoupledSinkPropertyType, true){ } CoupledSink::~CoupledSink(){ } std::string CoupledSink::ToString() const { std::string ret = PropertyName::wfd_coupled_sink + std::string(SEMICOLON) + std::string(SPACE); if (is_none()) { ret += NONE; } else { MAKE_HEX_STRING_2(status, status_); ret += status + std::string(SPACE); if (sink_address_ != ULLONG_MAX) { MAKE_HEX_STRING_12(sink_address, sink_address_); ret += sink_address; } else { ret += NONE; } } return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/coupledsink.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_COUPLEDSINK_H_ #define LIBWDS_RTSP_COUPLEDSINK_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class CoupledSink: public Property { public: CoupledSink(); CoupledSink(unsigned char status, unsigned long long int sink_address); ~CoupledSink() override; unsigned char status() const { return status_; } unsigned long long int sink_address() const { return sink_address_; } std::string ToString() const override; private: unsigned short status_; unsigned long long int sink_address_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_COUPLEDSINK_H_ ================================================ FILE: libwds/rtsp/displayedid.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/displayedid.h" #include "libwds/rtsp/macros.h" namespace wds { namespace rtsp { DisplayEdid::DisplayEdid(): Property(DisplayEdidPropertyType, true) { } DisplayEdid::DisplayEdid(unsigned short edid_block_count, const std::string& edid_payload) : Property(DisplayEdidPropertyType), edid_block_count_(edid_block_count), edid_payload_(edid_payload.length() ? edid_payload : NONE) { } DisplayEdid::~DisplayEdid() { } std::string DisplayEdid::ToString() const { std::string ret = PropertyName::wfd_display_edid + std::string(SEMICOLON) + std::string(SPACE); if (is_none()) { ret += NONE; } else { MAKE_HEX_STRING_2(edid_block_count, edid_block_count_); ret += edid_block_count + std::string(SPACE) + edid_payload_; } return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/displayedid.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_DISPLAYEDID_H_ #define LIBWDS_RTSP_DISPLAYEDID_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class DisplayEdid: public Property { public: DisplayEdid(); DisplayEdid(unsigned short edid_block_count, const std::string& edid_payload); ~DisplayEdid() override; unsigned short block_count() const { return edid_block_count_; } const std::string& payload() const { return edid_payload_; } std::string ToString() const override; private: unsigned short edid_block_count_; std::string edid_payload_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_DISPLAYEDID_H_ ================================================ FILE: libwds/rtsp/driver.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/driver.h" #include #include #include "libwds/public/logging.h" #include "libwds/rtsp/message.h" #include "libwds/rtsp/reply.h" #include "errorscanner.h" #include "headerscanner.h" #include "messagescanner.h" int wds_lex(YYSTYPE* yylval, void* scanner, std::unique_ptr& message) { if (!message) { return header_lex(yylval, scanner); } else if (message->is_reply()) { wds::rtsp::Reply* reply = static_cast(message.get()); if (reply->response_code() == wds::rtsp::STATUS_SeeOther) return error_lex(yylval, scanner); return message_lex(yylval, scanner); } return message_lex(yylval, scanner); } void wds_error(void* scanner, std::unique_ptr& message, const char* error_message) { WDS_ERROR("Parser error: %s", error_message); message.reset(nullptr); } namespace wds { namespace rtsp { void Driver::Parse(const std::string& input, std::unique_ptr& message) { void* scanner = nullptr; #if YYDEBUG bool enable_debug = true; wds_debug = 1; #else bool enable_debug = false; #endif if (!message) { header_lex_init(&scanner); header_set_debug(enable_debug, scanner); header__scan_string(input.c_str(), scanner); wds_parse(scanner, message); header_lex_destroy(scanner); } else if (message->is_reply()) { Reply* reply = static_cast(message.get()); if (reply->response_code() == STATUS_SeeOther) { error_lex_init(&scanner); error_set_debug(enable_debug, scanner); error__scan_string(input.c_str(), scanner); wds_parse(scanner, message); error_lex_destroy(scanner); } else { message_lex_init(&scanner); message_set_debug(enable_debug, scanner); message_set_extra(message->is_reply(), scanner); message__scan_string(input.c_str(), scanner); wds_parse(scanner, message); message_lex_destroy(scanner); } } else { message_lex_init(&scanner); message_set_debug(enable_debug, scanner); message__scan_string(input.c_str(), scanner); wds_parse(scanner, message); message_lex_destroy(scanner); } } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/driver.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_DRIVER_H_ #define LIBWDS_RTSP_DRIVER_H_ #include #include #include "parser.h" namespace wds { namespace rtsp { class Message; class Driver { public: static void Parse(const std::string& input, std::unique_ptr& message /*out*/); }; } // namespace rtsp } // namespace wds // Required by bison. int wds_lex(YYSTYPE* yylval, void* scanner, std::unique_ptr& message); void wds_error (void* scanner, std::unique_ptr& message, const char* error_message); #endif // LIBWDS_RTSP_DRIVER_H_ ================================================ FILE: libwds/rtsp/errorlexer.l ================================================ %option nodefault nounput nomain %option bison-bridge reentrant noyywrap %option never-interactive %option warn stack noyy_top_state noyy_pop_state noyy_push_state %option case-insensitive %option extra-type="bool" %option outfile="gen/errorscanner.cpp" header-file="gen/errorscanner.h" %top{ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #define YY_NO_UNISTD_H 1 } %{ #include #include "parser.h" #define yyterminate() return(END) %} DIGITS [0-9]+ SP [ \t] CR [\r] LF [\n] CRLF {CR}{LF} %% /* skip these */ {CRLF} { } {LF} { } {CR} { } /* Convert these */ "," { return ','; } ":" { return ':'; } {SP}+ return WFD_SP; ^"wfd_audio_codecs" { return WFD_AUDIO_CODECS_ERROR; } ^"wfd_video_formats" { return WFD_VIDEO_FORMATS_ERROR; } ^"wfd_3d_video_formats" { return WFD_3D_FORMATS_ERROR; } ^"wfd_content_protection" { return WFD_CONTENT_PROTECTION_ERROR; } ^"wfd_display_edid" { return WFD_DISPLAY_EDID_ERROR; } ^"wfd_coupled_sink" { return WFD_COUPLED_SINK_ERROR; } ^"wfd_trigger_method" { return WFD_TRIGGER_METHOD_ERROR; } ^"wfd_presentation_url" { return WFD_PRESENTATION_URL_ERROR; } ^"wfd_client_rtp_ports" { return WFD_CLIENT_RTP_PORTS_ERROR; } ^"wfd_route" { return WFD_ROUTE_ERROR; } ^"wfd_I2C" { return WFD_I2C_ERROR; } ^"wfd_av_format_change_timing" { return WFD_AV_FORMAT_CHANGE_TIMING_ERROR; } ^"wfd_preferred_display_mode" { return WFD_PREFERRED_DISPLAY_MODE_ERROR; } ^"wfd_uibc_capability" { return WFD_UIBC_CAPABILITY_ERROR; } ^"wfd_uibc_setting" { return WFD_UIBC_SETTING_ERROR; } ^"wfd_standby_resume_capability" { return WFD_STANDBY_RESUME_CAPABILITY_ERROR; } ^"wfd_standby" { return WFD_STANDBY_ERROR; } ^"wfd_connector_type" { return WFD_CONNECTOR_TYPE_ERROR; } ^"wfd_idr_request" { return WFD_IDR_REQUEST_ERROR; } ^[[:alpha:]][[:alnum:]\-\_]* { yylval->sval = new std::string(yytext, yyleng); return WFD_GENERIC_PROPERTY_ERROR; } {DIGITS} { std::string str(yytext, yyleng); str += '\0'; errno = 0; yylval->nval = strtoull(str.c_str(), NULL, 10); if (errno) yyterminate(); return WFD_NUM; } /* all unmatched */ <*>. {} %% ================================================ FILE: libwds/rtsp/formats3d.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/formats3d.h" #include "libwds/rtsp/macros.h" namespace wds { namespace rtsp { Formats3d::Formats3d() : Property(Video3DFormatsPropertyType, true) { } Formats3d::Formats3d(unsigned char native, unsigned char preferred_display_mode, const H264Codecs3d& h264_codecs_3d) : Property(Video3DFormatsPropertyType), native_(native), preferred_display_mode_(preferred_display_mode), h264_codecs_3d_(h264_codecs_3d) { } Formats3d::~Formats3d() { // TODO Auto-generated destructor stub } std::string H264Codec3d::ToString() const { std::string ret; MAKE_HEX_STRING_2(profile, profile_); MAKE_HEX_STRING_2(level, level_); MAKE_HEX_STRING_16(video_capability_3d, video_capability_3d_); MAKE_HEX_STRING_2(latency,latency_); MAKE_HEX_STRING_4(min_slice_size, min_slice_size_); MAKE_HEX_STRING_4(slice_enc_params, slice_enc_params_); MAKE_HEX_STRING_2(frame_rate_control_support, frame_rate_control_support_); ret = profile + std::string(SPACE) + level + std::string(SPACE) + video_capability_3d + std::string(SPACE) + latency + std::string(SPACE) + min_slice_size + std::string(SPACE) + slice_enc_params + std::string(SPACE) + frame_rate_control_support + std::string(SPACE); if (max_hres_ > 0) { MAKE_HEX_STRING_4(max_hres, max_hres_); ret += max_hres; } else { ret += NONE; } ret += std::string(SPACE); if (max_vres_ > 0) { MAKE_HEX_STRING_4(max_vres, max_vres_); ret += max_vres; } else { ret += NONE; } return ret; } std::string Formats3d::ToString() const { std::string ret; ret = PropertyName::wfd_3d_video_formats + std::string(SEMICOLON)+ std::string(SPACE); if (is_none()) return ret + NONE; MAKE_HEX_STRING_2(native, native_); MAKE_HEX_STRING_2(preferred_display_mode, preferred_display_mode_); ret += native + std::string(SPACE) + preferred_display_mode + std::string(SPACE); auto it = h264_codecs_3d_.begin(); auto end = h264_codecs_3d_.end(); while(it != end) { ret += (*it).ToString(); ++it; if (it != end) ret += ", "; } return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/formats3d.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_FORMATS3D_H_ #define LIBWDS_RTSP_FORMATS3D_H_ #include "libwds/rtsp/property.h" #include namespace wds { namespace rtsp { // todo(shalamov): refactor, looks almost similar to VideoFormats struct H264Codec3d { public: H264Codec3d(unsigned char profile, unsigned char level, unsigned long long int video_capability_3d, unsigned char latency, unsigned short min_slice_size, unsigned short slice_enc_params, unsigned char frame_rate_control_support, unsigned short max_hres, unsigned short max_vres) : profile_(profile), level_(level), video_capability_3d_(video_capability_3d), latency_(latency), min_slice_size_(min_slice_size), slice_enc_params_(slice_enc_params), frame_rate_control_support_(frame_rate_control_support), max_hres_(max_hres), max_vres_(max_vres) {} std::string ToString() const; unsigned char profile_; unsigned char level_; unsigned long long int video_capability_3d_; unsigned char latency_; unsigned short min_slice_size_; unsigned short slice_enc_params_; unsigned char frame_rate_control_support_; unsigned short max_hres_; unsigned short max_vres_; }; typedef std::vector H264Codecs3d; class Formats3d: public Property { public: Formats3d(); Formats3d(unsigned char native, unsigned char preferred_display_mode, const H264Codecs3d& h264_codecs_3d); ~Formats3d() override; unsigned char native_resolution() const { return native_; } unsigned char preferred_display_mode() const { return preferred_display_mode_;} const H264Codecs3d& codecs() const { return h264_codecs_3d_; } std::string ToString() const override; private: unsigned char native_; unsigned char preferred_display_mode_; H264Codecs3d h264_codecs_3d_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_FORMATS3D_H_ ================================================ FILE: libwds/rtsp/genericproperty.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include "libwds/rtsp/genericproperty.h" namespace wds { namespace rtsp { GenericProperty::GenericProperty() : Property(GenericPropertyType) { } GenericProperty::GenericProperty(const std::string& key, const std::string& value) : Property(GenericPropertyType), key_(key), value_(value) { } GenericProperty::~GenericProperty() { } std::string GenericProperty::ToString() const { return key_ + ": " + value_; } std::string GenericProperty::GetName() const { return key_; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/genericproperty.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_GENERIC_PROPERTY_H_ #define LIBWDS_RTSP_GENERIC_PROPERTY_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class GenericProperty: public Property { public: GenericProperty(); GenericProperty(const std::string& key, const std::string& value); ~GenericProperty() override; const std::string& key() const { return key_; } const std::string& value() const { return value_; } std::string ToString() const override; std::string GetName() const override; private: std::string key_; std::string value_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_GENERIC_PROPERTY_H_ ================================================ FILE: libwds/rtsp/getparameter.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/getparameter.h" namespace wds { namespace rtsp { GetParameter::GetParameter(const std::string& request_uri) : Request(Request::MethodGetParameter, request_uri) { } GetParameter::~GetParameter() { } std::string GetParameter::ToString() const { std::string ret = MethodName::GET_PARAMETER + std::string(SPACE) + request_uri() + std::string(SPACE) + std::string(RTSP_END) + std::string(CRLF); return ret + Message::ToString(); } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/getparameter.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_GETPARAMETER_H_ #define LIBWDS_RTSP_GETPARAMETER_H_ #include "libwds/rtsp/message.h" namespace wds { namespace rtsp { class GetParameter : public Request { public: explicit GetParameter(const std::string& request_uri); ~GetParameter() override; std::string ToString() const override; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_GETPARAMETER_H_ ================================================ FILE: libwds/rtsp/header.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/header.h" #include namespace wds { namespace rtsp { namespace { const char kContentLenght[] = "Content-Length: "; const char kContentType[] = "Content-Type: "; const char kContentLength[] = "Content-Length: "; const char kCSeq[] = "CSeq: "; const char kSession[] = "Session: "; const char kTimeout[] = ";timeout="; const char kPublic[] = "Public: "; const char kRequire[] = "Require: org.wfa.wfd1.0"; } Header::Header() : cseq_(0), content_length_(0), timeout_(0), require_wfd_support_(false) { } Header::~Header() { } int Header::cseq() const { return cseq_; } void Header::set_cseq(int cseq) { cseq_ = cseq; } int Header::content_length() const { return content_length_; } void Header::set_content_length(int content_length) { content_length_ = content_length; } const std::string& Header::content_type() const { return content_type_; } void Header::set_content_type(const std::string& content_type) { content_type_ = content_type; } const std::string& Header::session() const { return session_; } void Header::set_session(const std::string& session) { session_ = session; } unsigned int Header::timeout() const { return timeout_; } void Header::set_timeout(int timeout) { timeout_ = timeout; } TransportHeader& Header::transport() const { if (!transport_) transport_.reset(new TransportHeader()); return *transport_; } void Header::set_transport(TransportHeader* transport) { transport_.reset(transport); } bool Header::require_wfd_support() const { return require_wfd_support_; } void Header::set_require_wfd_support(bool require_wfd_support) { require_wfd_support_ = require_wfd_support; } const std::vector& Header::supported_methods() const { return supported_methods_; } void Header::add_generic_header(const std::string& key ,const std::string& value) { generic_headers_[key] = value; } const GenericHeaderMap& Header::generic_headers() const { return generic_headers_; } void Header::set_supported_methods( const std::vector& supported_methods) { supported_methods_ = supported_methods; } bool Header::has_method(const Method& method) const { return std::find (supported_methods_.begin(), supported_methods_.end(), method) != supported_methods_.end(); } std::string Header::ToString() const { std::string ret; ret += kCSeq + std::to_string(cseq_) + CRLF; if (!session_.empty()) { if (timeout_ > 0) ret += kSession + session_ + kTimeout + std::to_string(timeout_) + CRLF; else ret += kSession + session_ + CRLF; } if (content_type_.length()) ret += kContentType + content_type_ + CRLF; if (content_length_) ret += kContentLenght + std::to_string(content_length_) + CRLF; ret += transport().ToString(); if (supported_methods_.size()) { auto i = supported_methods_.begin(); auto end = supported_methods_.end(); ret += kPublic; while (i != end) { ret += MethodName::name[*i]; if (i != --supported_methods_.end()) { ret += ", "; } ++i; } ret += CRLF; } if (require_wfd_support_) ret += std::string(kRequire) + CRLF; for (auto it = generic_headers_.begin(); it != generic_headers_.end(); it++) ret += (*it).first + ": " + (*it).second + CRLF; return ret + CRLF; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/header.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_HEADER_H_ #define LIBWDS_RTSP_HEADER_H_ #include #include #include #include #include "libwds/rtsp/constants.h" #include "libwds/rtsp/transportheader.h" typedef std::map GenericHeaderMap; namespace wds { namespace rtsp { class Header { public: Header(); virtual ~Header(); int cseq() const; void set_cseq(int cseq); int content_length() const; void set_content_length(int content_length); const std::string& content_type() const; void set_content_type(const std::string& content_type); const std::string& session() const; void set_session(const std::string& session); unsigned int timeout() const; void set_timeout(int timeout); TransportHeader& transport() const; void set_transport(TransportHeader* transport); bool require_wfd_support() const; void set_require_wfd_support(bool require_wfd_support); const std::vector& supported_methods() const; void set_supported_methods(const std::vector& supported_methods); bool has_method(const Method& method) const; void add_generic_header(const std::string& key ,const std::string& value); const GenericHeaderMap& generic_headers () const; std::string ToString() const; private: int cseq_; int content_length_; unsigned int timeout_; std::string session_; mutable std::unique_ptr transport_; std::string content_type_; bool require_wfd_support_; std::vector supported_methods_; GenericHeaderMap generic_headers_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_HEADER_H_ ================================================ FILE: libwds/rtsp/headerlexer.l ================================================ %option nodefault nounput nomain %option bison-bridge reentrant noyywrap %option never-interactive %option warn stack noyy_top_state noyy_pop_state noyy_push_state %option case-insensitive %option extra-type="bool" %option outfile="gen/headerscanner.cpp" header-file="gen/headerscanner.h" %top{ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #define YY_NO_UNISTD_H 1 } %{ #include #include "parser.h" #define yyterminate() return(END) %} %x MATCH_STRING_STATE %x MATCH_RESPONSE_CODE_STATE %s SUPPORTED_METHODS_STATE %s CONTENT_TYPE_STATE %s SESSION_STATE DIGIT [0-9] DIGITS [0-9]+ HEXDIG [0-9a-fA-F] HEXDIGITS [0-9a-fA-F]+ SP [ \t] CR [\r] LF [\n] CRLF {CR}{LF} %% <*>{CRLF} { BEGIN(INITIAL); } <*>{LF} { BEGIN(INITIAL); } <*>{CR} { BEGIN(INITIAL); } /* Convert these */ "=" { return '='; } "-" { return '-'; } "," { return ','; } "\*" { return '*'; } ";" { return ';'; } ":" { return ':'; } "/" { return '/'; } {SP}+ return WFD_SP; ";timeout=" return WFD_TIMEOUT; ";server_port=" return WFD_SERVER_PORT; ^(?-i:"OPTIONS") { BEGIN(INITIAL); return WFD_OPTIONS; } ^(?-i:"SET_PARAMETER") { BEGIN(INITIAL); return WFD_SET_PARAMETER; } ^(?-i:"GET_PARAMETER") { BEGIN(INITIAL); return WFD_GET_PARAMETER; } ^(?-i:"SETUP") { BEGIN(INITIAL); return WFD_SETUP; } ^(?-i:"PLAY") { BEGIN(INITIAL); return WFD_PLAY; } ^(?-i:"TEARDOWN") { BEGIN(INITIAL); return WFD_TEARDOWN; } ^(?-i:"PAUSE") { BEGIN(INITIAL); return WFD_PAUSE; } /* RTSP response, get reply code, RTSP/1.0 200 OK */ ^"RTSP/"{DIGIT}"."{DIGIT}{SP}+ { BEGIN(MATCH_RESPONSE_CODE_STATE); return WFD_RESPONSE; } /* CSeq: i */ ^"CSeq:" { BEGIN(INITIAL); return WFD_CSEQ; } ^"Public:" { BEGIN(SUPPORTED_METHODS_STATE); return WFD_RESPONSE_METHODS; } ^"Require: org.wfa.wfd1.0" { return WFD_SUPPORT_CHECK; } ^"Content-Type:" { BEGIN(CONTENT_TYPE_STATE); return WFD_CONTENT_TYPE; } ^"Content-Length:" { BEGIN(INITIAL); return WFD_CONTENT_LENGTH; } ^"Session:" { BEGIN(SESSION_STATE); return WFD_SESSION; } ^"Transport: RTP/AVP/UDP;unicast;client_port=" { return WFD_TRANSPORT; } ^[[:alpha:]][[:alnum:]\-\_]*":" { BEGIN(MATCH_STRING_STATE); yylval->sval = new std::string(yytext, yyleng - 1); return WFD_HEADER; } [^ ;\t\r\n]+ { BEGIN(INITIAL); yylval->sval = new std::string(yytext, yyleng); return WFD_SESSION_ID; } {DIGITS} { BEGIN(MATCH_STRING_STATE); yylval->nval = atoi(yytext); return WFD_RESPONSE_CODE; } [^ \r\n][^\r\n]+/"\r\n" { BEGIN(INITIAL); yylval->sval = new std::string(yytext); return WFD_STRING; } "OPTIONS" { return WFD_OPTIONS; } "SET_PARAMETER" { return WFD_SET_PARAMETER; } "GET_PARAMETER" { return WFD_GET_PARAMETER; } "SETUP" { return WFD_SETUP; } "PLAY" { return WFD_PLAY; } "TEARDOWN" { return WFD_TEARDOWN; } "PAUSE" { return WFD_PAUSE; } "org.wfa.wfd1.0" { return WFD_TAG; } [-[:alnum:]]+\/[-[:alnum:]]+ { BEGIN(INITIAL); yylval->sval = new std::string(yytext); return WFD_MIME; } {DIGITS} { std::string str(yytext, yyleng); str += '\0'; errno = 0; yylval->nval = strtoull(str.c_str(), NULL, 10); if (errno) yyterminate(); return WFD_NUM; } /* RTSP request rule, e.g., OPTIONS * RTSP/1.0 */ "RTSP/"{DIGIT}"."{DIGIT} { return WFD_END; } /* GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0 */ "rtsp://"[^ \t\n]+ { yylval->sval = new std::string(yytext); return WFD_REQUEST_URI; } /* all unmatched */ <*>. {} %% ================================================ FILE: libwds/rtsp/i2c.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/i2c.h" namespace wds { namespace rtsp { I2C::I2C(int port) : Property(I2CPropertyType), port_(port) { } I2C::~I2C() { } std::string I2C::ToString() const { std::string ret = PropertyName::wfd_I2C + std::string(SEMICOLON) + std::string(SPACE) + (is_supported() ? std::to_string(port()) : NONE); return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/i2c.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_I2C_H_ #define LIBWDS_RTSP_I2C_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class I2C: public Property { public: explicit I2C(int port); ~I2C() override; bool is_supported() const { return port_ > 0; } int port() const { return port_; } std::string ToString() const override; private: int port_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_I2C_H_ ================================================ FILE: libwds/rtsp/idrrequest.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/idrrequest.h" namespace wds { namespace rtsp { IDRRequest::IDRRequest() : Property(IDRRequestPropertyType) { } IDRRequest::~IDRRequest() { } std::string IDRRequest::ToString() const { return std::string("wfd_idr_request"); } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/idrrequest.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_IDRREQUEST_H_ #define LIBWDS_RTSP_IDRREQUEST_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class IDRRequest: public Property { public: IDRRequest(); ~IDRRequest() override; std::string ToString() const override; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_IDRREQUEST_H_ ================================================ FILE: libwds/rtsp/macros.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_MACROS_H_ #define LIBWDS_RTSP_MACROS_H_ #include #define MAKE_HEX_STRING_2(NAME, PROPERTY) \ char NAME[3]; \ std::snprintf(NAME, sizeof(NAME), "%02X", PROPERTY) \ #define MAKE_HEX_STRING_4(NAME, PROPERTY) \ char NAME[5]; \ std::snprintf(NAME, sizeof(NAME), "%04X", PROPERTY) \ #define MAKE_HEX_STRING_6(NAME, PROPERTY) \ char NAME[7]; \ std::snprintf(NAME, sizeof(NAME), "%06X", PROPERTY) \ #define MAKE_HEX_STRING_8(NAME, PROPERTY) \ char NAME[9]; \ std::snprintf(NAME, sizeof(NAME), "%08X", PROPERTY) \ #define MAKE_HEX_STRING_10(NAME, PROPERTY) \ char NAME[11]; \ std::snprintf(NAME, sizeof(NAME), "%010llX", PROPERTY) \ #define MAKE_HEX_STRING_12(NAME, PROPERTY) \ char NAME[13]; \ std::snprintf(NAME, sizeof(NAME), "%012llX", PROPERTY) \ #define MAKE_HEX_STRING_16(NAME, PROPERTY) \ char NAME[17]; \ std::snprintf(NAME, sizeof(NAME), "%016llX", PROPERTY) \ #endif // LIBWDS_RTSP_MACROS_H_ ================================================ FILE: libwds/rtsp/message.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/message.h" #include namespace wds { namespace rtsp { namespace { const char kDefaultContentType[] = "text/parameters"; } Message::Message(Type type) : type_(type) { } Message::~Message() { } int Message::cseq() const { assert(header_); return header_->cseq(); } Header& Message::header() { if (!header_) header_.reset(new Header()); return *header_; } std::string Message::ToString() const { std::string ret; if (payload_) ret = payload_->ToString(); if (header_) { header_->set_content_length (ret.length()); if(ret.length() > 0 && header_->content_type().length() == 0) header_->set_content_type (kDefaultContentType); ret = header_->ToString() + ret; } return ret; } Request::Request(RTSPMethod method, const std::string& request_uri) : Message(REQUEST), id_(UNKNOWN), method_(method), request_uri_(request_uri) { } Request::~Request() { } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/message.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_MESSAGE_H_ #define LIBWDS_RTSP_MESSAGE_H_ #include #include "libwds/rtsp/header.h" #include "libwds/rtsp/payload.h" namespace wds { namespace rtsp { class Message { public: enum Type { REQUEST, REPLY }; explicit Message(Type type); virtual ~Message(); bool is_reply() const { return type_ == REPLY; } bool is_request() const { return type_ == REQUEST; } int cseq() const; void set_header(std::unique_ptr
header) { header_ = std::move(header); } Header& header(); void set_payload(std::unique_ptr payload) { payload_ = std::move(payload); } Payload* payload() { return payload_.get(); } virtual std::string ToString() const; protected: std::unique_ptr
header_; std::unique_ptr payload_; private: Type type_; }; class Request : public Message { public: enum ID { UNKNOWN, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14, M15, M16 }; enum RTSPMethod { MethodOptions = 1, MethodSetParameter, MethodGetParameter, MethodSetup, MethodPlay, MethodTeardown, MethodPause }; Request(RTSPMethod method, const std::string& request_uri = std::string()); ~Request() override; const std::string& request_uri() const { return request_uri_; } void set_request_uri(const std::string& request_uri) { request_uri_ = request_uri; } ID id() const { return id_; } void set_id(ID id) { id_ = id; } RTSPMethod method() const { return method_; } void set_method(RTSPMethod method) { method_ = method; } private: ID id_; RTSPMethod method_; std::string request_uri_; }; inline Request* ToRequest(Message* message) { return static_cast(message); } } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_MESSAGE_H_ ================================================ FILE: libwds/rtsp/messagelexer.l ================================================ %option nodefault nounput nomain %option bison-bridge reentrant noyywrap %option never-interactive %option warn stack noyy_top_state noyy_pop_state noyy_push_state %option case-insensitive %option extra-type="bool" %option outfile="gen/messagescanner.cpp" header-file="gen/messagescanner.h" %top{ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #define YY_NO_UNISTD_H 1 } %{ #include #include "parser.h" #define yyterminate() return(END) %} %x MATCH_STRING_STATE %x MATCH_RESPONSE_CODE_STATE %s SUPPORTED_METHODS_STATE %s CONTENT_TYPE_STATE %s SESSION_STATE %s MATCH_PRESENTATION_URL %s NUM_AS_HEX_MODE %s MATCH_EDID_STATE DIGIT [0-9] DIGITS [0-9]+ HEXDIG [0-9a-fA-F] HEXDIGITS [0-9a-fA-F]+ SP [ \t] CR [\r] LF [\n] CRLF {CR}{LF} IPADDRESS (([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) IPPORT [:]({DIGIT}){1,5} %% <*>{CRLF} { BEGIN(INITIAL); } <*>{LF} { BEGIN(INITIAL); } <*>{CR} { BEGIN(INITIAL); } /* Convert these */ "=" { return '='; } "-" { return '-'; } "," { return ','; } "\*" { return '*'; } ";" { return ';'; } ":" { return ':'; } "/" { return '/'; } {SP}+ return WFD_SP; "none" return WFD_NONE; "LPCM" return WFD_AUDIO_CODEC_LPCM; "AAC" return WFD_AUDIO_CODEC_AAC; "AC3" return WFD_AUDIO_CODEC_AC3; "HDCP2.0" return WFD_HDCP_SPEC_2_0; "HDCP2.1" return WFD_HDCP_SPEC_2_1; "port=" return WFD_IP_PORT; "RTP/AVP/UDP;unicast" return WFD_STREAM_PROFILE; "mode=play" return WFD_MODE_PLAY; "primary" return WFD_ROUTE_PRIMARY; "secondary" return WFD_ROUTE_SECONDARY; "input_category_list=" return WFD_INPUT_CATEGORY_LIST; "GENERIC" return WFD_INPUT_CATEGORY_GENERIC; "HIDC" return WFD_INPUT_CATEGORY_HIDC; "generic_cap_list=" return WFD_GENERIC_CAP_LIST; "Keyboard" return WFD_INPUT_TYPE_KEYBOARD; "Mouse" return WFD_INPUT_TYPE_MOUSE; "SingleTouch" return WFD_INPUT_TYPE_SINGLE_TOUCH; "MultiTouch" return WFD_INPUT_TYPE_MULTI_TOUCH; "Joystick" return WFD_INPUT_TYPE_JOYSTICK; "Camera" return WFD_INPUT_TYPE_CAMERA; "Gesture" return WFD_INPUT_TYPE_GESTURE; "RemoteControl" return WFD_INPUT_TYPE_REMOTE_CONTROL; "hidc_cap_list=" return WFD_HIDC_CAP_LIST; "Infrared" return WFD_INPUT_PATH_INFRARED; "USB" return WFD_INPUT_PATH_USB; "BT" return WFD_INPUT_PATH_BT; "Wi-Fi" return WFD_INPUT_PATH_WIFI; "Zigbee" return WFD_INPUT_PATH_ZIGBEE; "No-SP" return WFD_INPUT_PATH_NOSP; "disable" return WFD_UIBC_SETTING_DISABLE; "enable" return WFD_UIBC_SETTING_ENABLE; "supported" return WFD_SUPPORTED; {DIGITS} { std::string str(yytext, yyleng); str += '\0'; errno = 0; yylval->nval = strtoull(str.c_str(), NULL, 16); if (errno) yyterminate(); return WFD_NUM; } {HEXDIGITS} { std::string str(yytext, yyleng); str += '\0'; errno = 0; yylval->nval = strtoull(str.c_str(), NULL, 16); if (errno) yyterminate(); return WFD_NUM; } {DIGITS} { yylval->sval = new std::string(yytext); return WFD_STRING; } {HEXDIGITS} { yylval->sval = new std::string(yytext); return WFD_STRING; } ^"wfd_audio_codecs" { BEGIN(NUM_AS_HEX_MODE); return WFD_AUDIO_CODECS; } ^"wfd_video_formats" { BEGIN(NUM_AS_HEX_MODE); return WFD_VIDEO_FORMATS; } ^"wfd_3d_video_formats" { BEGIN(NUM_AS_HEX_MODE); return WFD_3D_FORMATS; } ^"wfd_content_protection" { return WFD_CONTENT_PROTECTION; } ^"wfd_display_edid" { BEGIN(MATCH_EDID_STATE); return WFD_DISPLAY_EDID; } ^"wfd_coupled_sink" { BEGIN(NUM_AS_HEX_MODE); return WFD_COUPLED_SINK; } ^"wfd_trigger_method" { BEGIN(SUPPORTED_METHODS_STATE); return WFD_TRIGGER_METHOD; } ^"wfd_presentation_url" { BEGIN(MATCH_PRESENTATION_URL); return WFD_PRESENTATION_URL; } ^"wfd_client_rtp_ports" { return WFD_CLIENT_RTP_PORTS; } ^"wfd_route" { return WFD_ROUTE; } ^"wfd_I2C" { return WFD_I2C; } ^"wfd_av_format_change_timing" { BEGIN(NUM_AS_HEX_MODE); return WFD_AV_FORMAT_CHANGE_TIMING; } ^"wfd_preferred_display_mode" { BEGIN(NUM_AS_HEX_MODE); return WFD_PREFERRED_DISPLAY_MODE; } ^"wfd_uibc_capability" { return WFD_UIBC_CAPABILITY; } ^"wfd_uibc_setting" { return WFD_UIBC_SETTING; } ^"wfd_standby_resume_capability" { return WFD_STANDBY_RESUME_CAPABILITY; } ^"wfd_standby" { if (yyextra) // Is reply. return WFD_STANDBY_IN_RESPONSE; return WFD_STANDBY_IN_REQUEST; } ^"wfd_connector_type" { BEGIN(NUM_AS_HEX_MODE); return WFD_CONNECTOR_TYPE; } ^"wfd_idr_request" { return WFD_IDR_REQUEST; } ^[[:alpha:]][[:alnum:]\-\_]* { BEGIN(MATCH_STRING_STATE); yylval->sval = new std::string(yytext, yyleng); return WFD_GENERIC_PROPERTY; } {DIGITS} { std::string str(yytext, yyleng); str += '\0'; errno = 0; yylval->nval = strtoull(str.c_str(), NULL, 10); if (errno) yyterminate(); return WFD_NUM; } [^ :\r\n][^\r\n]+/"\r\n" { BEGIN(INITIAL); yylval->sval = new std::string(yytext); return WFD_STRING; } "OPTIONS" { return WFD_OPTIONS; } "SET_PARAMETER" { return WFD_SET_PARAMETER; } "GET_PARAMETER" { return WFD_GET_PARAMETER; } "SETUP" { return WFD_SETUP; } "PLAY" { return WFD_PLAY; } "TEARDOWN" { return WFD_TEARDOWN; } "PAUSE" { return WFD_PAUSE; } "org.wfa.wfd1.0" { return WFD_TAG; } "rtsp://"{IPADDRESS}{IPPORT}?"/wfd1.0/streamid=0" { yylval->sval = new std::string(yytext); return WFD_PRESENTATION_URL_0; } "rtsp://"{IPADDRESS}{IPPORT}?"/wfd1.0/streamid=1" { yylval->sval = new std::string(yytext); return WFD_PRESENTATION_URL_1; } /* all unmatched */ <*>. {} %% ================================================ FILE: libwds/rtsp/messages_rules.txt ================================================ Rules and lexer DIGIT = %x30-39 HEXDIG = DIGIT / %x41-46 SP = %x20 CR = %x0D LF = %x0A CRLF = CR LF IPADDRESS = 1*3(DIGIT) “.” 1*3(DIGIT) “.” 1*3(DIGIT) “.” 1*3(DIGIT) IPPORT = 1*5(DIGIT) RULE wfd-audio-codecs wfd-audio-codecs = “wfd_audio_codecs:” SP sink-audio-cap CRLF sink-audio-cap = “none” / sink-audio-list; “none” if not supported at a sink-audio-list = audio-format SP modes SP latency *(“,” SP sink-audio-list) audio-format = “LPCM” / “AAC” / “AC3” modes = 8*8HEXDIG; see Table 5-21, Table 5-22 and Table 5-23 latency = 2*2HEXDIG; decoder latency in units of 5 msecs, see LPCM decoder latency field for LPCM, see AAC decoder latency field for AAC and see AC3 decoder latency field in Table 5-20 for more detail RULE wfd-video-formats wfd-video-formats = “wfd_video_formats:” SP sink-video-list CRLF sink-video-list = “none” / (native SP preferred-display-mode-supported SP H.264-codec);the Secondary Sink shall return “none” native = 2*2HEXDIG; see Table 5-13 preferred-display-mode-supported = 2*2HEXDIG; 0-not supported, 1-supported, 2-255 reserved H.264-codec = profile SP level SP misc-params SP max-hres SP max-vres *(“,” SP H.264-codec) profile = 2*2HEXDIG; see Table 5-14, only one bit set level = 2*2HEXDIG; see Table 5-15, only one bit set max-hres = “none” / (4*4HEXDIG); in M3 response and if preferred-display mode-supported is 0, then “none”. in M3 response and if preferred-display-mode- supported is 1, specifies the maximum horizontal resolution that the H.264 decoder supports in pixels. in M4 request, it is “none” and the recipient shall ignore this subparameter max-vres = “none” / (4*4HEXDIG); in M3 response and if preferred-display mode-supported is 0, then “none”. in M3 response and if preferred-display-mode- supported is 1, specifies the maximum vertical resolution that the H.264 decoder supports in pixels. in M4 request, it is “none” and the recipient shall ignore this subparameter misc-params = SP VESA-Support SP HH-Support SP latency SP min-slice-size SP slice-enc-params SP frame-rate-control-support CEA-Support CEA-Support = 8*8HEXDIG; see Table 5-10. when used inside preferred display mode in M4 request, this subfield should be set to 0x00000000 and the recipient shall ignore this subfield. VESA-Support = 8*8HEXDIG; see Table 5-11. when used inside preferred display mode in M4 request, this subfield should be set to 0x00000000 and the recipient shall ignore this subfield. HH-Support = 8*8HEXDIG; see Table 5-12. when used inside preferred display mode in M4 request, this subfield should be set to 0x00000000 and the recipient shall ignore this subfield. latency = 2*2HEXDIG; decoder latency in units of 5 msecs, see latency field in Table 5-9 for more detail min-slice-size = 4*4HEXDIG; number of macroblocks slice-enc-params = 4*4HEXDIG; see Table 5-16 frame-rate-control-support = 2*2HEXDIG; see Table 5-17 RULE wfd-3d-formats wfd-3d-formats = “wfd_3d_video_formats:” SP 3d-cap CRLF 3d-cap = “none” / 3d-cap-list; if not supported then “none” 3d-cap-list = native SP preferred-display-mode-supported SP H.264-codec native = 2*2HEXDIG; see Table 5-13 preferred-display-mode-supported = 2*2HEXDIG; 0-not supported, 1-supported, 2-255 reserved H.264-codec = profile SP level SP misc-params SP max-hres SP max-vres * (“,” SP H.264-codec) profile = 2*2HEXDIG; see Table 5-14, only one bit set level = 2*2HEXDIG; see Table 5-15, only one bit set max-hres = “none” / (4*4HEXDIG); in M3 response and if preferred-display mode-supported is 0, then “none”. in M3 response and if preferred-display-mode-supported is 1, specifies the maximum horizontal resolution that the H.264 decoder supports in pixels. in M4 request, it is “none” and the recipient shall ignore this subparameter max-vres = “none” / (4*4HEXDIG); in M3 response and if preferred-display mode-supported is 0, then “none”. in M3 response and if preferred-display-mode-supported is 1, specifies the maximum vertical resolution that the H.264 decoder supports in pixels. in M4 request, it is “none” and the recipient shall ignore this subparameter misc-params = 3d-video-capability SP latency SP min-slice-size SP slice-enc-params SP frame-rate-control-support 3d-video-capability= 16*16HEXDIG; see Table 5-19. latency = 2*2HEXDIG; decoder latency in units of 5 msecs, see latency field in Table 5-9 for more detail min-slice-size = 4*4HEXDIG; number of macroblocks slice-enc-params = 4*4HEXDIG; see Table 5-16 frame-rate-control-support = 2*2HEXDIG; see Table 5-17 RULE wfd-content-protection wfd-content-protection = “wfd_content_protection:” SP cp-spec CRLF cp-spec = “none” / hdcp2-spec hdcp2-spec = (“HDCP2.0” / “HDCP2.1”) SP “port=” IPPORT ;TCP port RULE wfd-display-edid wfd-display-edid = “wfd_display_edid:” SP edid CRLF edid = “none” / (edid-block-count SP edid-payload) edid-block-count = 4*4HEXDIG; 0: if EDID is not available at the time that the WFD Sink responses to the parameter request. 1-256: number of 128-byte EDID blocks in edid-payload Other values: reserved edid-payload = “none” / 256*65536HEXDIG; “none” if edid-block-count is 0. Otherwise, edid-payload contains the entire EDID data structure available from the display device. Length of edid-payload shall be a multiple of 128 bytes. (length of edid-payload = edid-block-count * 128-byte) RULE wfd-coupled-sink wfd-coupled-sink = “wfd_coupled_sink:” SP coupled-sink-cap CRLF coupled-sink-cap = “none” /(status SP sink-address); “none” if Coupled Sink Operation is not supported status = 2*2HEXDIG; see Table 5-8 sink-address = “none” / (12*12HEXDIG); WFD Sink’s MAC address if status is Coupled otherwise “none”. RULE wfd-trigger-method wfd-trigger-method = “wfd_trigger_method:” SP (“SETUP” / “PAUSE” / “TEARDOWN” / “PLAY”) CRLF RULE wfd-presentation-url wfd-presentation-url = “wfd_presentation_URL:” SP wfd-url0 SP wfd-url1 CRLF wfd-url0 = “none” / (“rtsp://” source-ip-address“/wfd1.0/streamid=0”) wfd-url1 = “none” / (“rtsp://” source-ip-address“/wfd1.0/streamid=1”) source-ip-address = IPADDRESS RULE wfd-client-rtp-ports wfd-client-rtp-ports = “wfd_client_rtp_ports:” SP profile SP rtp-port0 SP rtp-port1 SP mode CRLF profile = “RTP/AVP/UDP;unicast” rtp-port0 = IPPORT ; UDP port rtp-port1 = IPPORT ; UDP port mode = “mode=play” RULE wfd-route wfd-route = “wfd_route:” SP destination CRLF destination = “primary” / “secondary” RULE wfd-I2C wfd-I2C = “wfd_I2C:” SP I2C-port CRLF I2C-port = “none” / IPPORT; port where the device listens for I2C commands, “none” if not supported RULE wfd-av-format-change-timing wfd-av-format-change-timing = “wfd_av_format_change_timing:” SP PTS SP DTS CRLF PTS = 10*10HEXDIG; most-significant 33 bits indicating PTS value DTS = 10*10HEXDIG; most-significant 33 bits indicating DTS value RULE wfd-preferred-display-mode wfd-preferred-display-mode = “wfd_preferred_display_mode:” SP dinfo CRLF dinfo = p-clock SP H SP HB SP HSPOL-HSOFF SP HSW SP V SP VB SP VSPOL-VSOFF SP VSW SP VBS3D SP 2d-s3d-modes SP p-depth SP H.264-codec p-clock = 6*6HEXDIG; pixel clock in 10kHz units H = 4*4HEXDIG; horizontal active resolution in units of pixels HB = 4*4HEXDIG; horizontal blanking period in units of pixels HSPOL-HSOFF = 4*4HEXDIG; b15: horizontal sync polarity (0 negative, 1 positive) b14:b0 horizontal sync offset in units of pixels HSW = 4*4HEXDIG; horizontal sync width in units of pixels V = 4*4HEXDIG; vertical active resolution in units of lines VB = 4*4HEXDIG; vertical blanking period in units of lines VSPOL-VSOFF = 4*4HEXDIG; b15: vertical sync polarity (0 negative, 1 positive) b14:b0 vertical sync offset in units of lines VSW = 4*4HEXDIG; vertical sync width in units of lines VBS3D = 2*2HEXDIG; vertical blanking interval in units of lines (only used in stereoscopic 3D Frame Packing mode) 2d-s3d-modes = 2*2HEXDIG; 2D/Stereoscopic 3D Modes (refer to Table 6-4) P-depth = 2*2HEXDIG; pixel depth (refer to Table 6-5). This is the pixel depth of the display output which is different from the codec pixel depth. H.264-codec = ; see section 6.1.3 RULE wfd-uibc-capability wfd-uibc-capability = “wfd_uibc_capability:” SP (“none” / (input-category-val “;” generic-cap-val “;” hidc-cap-val “;” tcp-port)) CRLF; “none” if not supported input-category-val = “input_category_list=” (“none” / input-category-list) input-category-list = input-cat * (“,” SP input-category-list) input-cat = “GENERIC” / “HIDC” generic-cap-val = “generic_cap_list=” (“none” / generic-cap-list) generic-cap-list = inp-type *(“,” SP generic-cap-list) inp-type = “Keyboard” / “Mouse” / “SingleTouch” / “MultiTouch” / “Joystick” / “Camera” / “Gesture” / “RemoteControl” hidc-cap-val = “hidc_cap_list=” (“none” / hidc-cap-list) hidc-cap-list = detailed-cap *(“,” SP hidc-cap-list) detailed-cap = inp-type “/” inp-path inp-path = “Infrared” / “USB” / “BT” / “Zigbee” / “Wi-Fi” / “No-SP” tcp-port = “port=” (“none” / IPPORT) RULE wfd-uibc-setting wfd-uibc-setting = “wfd_uibc_setting:” SP uibc-setting CRLF uibc-setting = “disable” / “enable” RULE wfd-standby-resume-capability wfd-standby-resume-capability = “wfd_standby_resume_capability:” SP standby-resume-cap CRLF standby-resume-cap = “none” / “supported”; “none” if not supported RULE wfd-standby wfd-standby = “wfd_standby” CRLF RULE wfd-connector-type wfd-connector-type = “wfd_connector_type:” SP connector-type CRLF connector-type = “none” / (2*2HEXDIG); specifies the active display connector type (see Table 6-6), “none” if the WFD Sink dongle that is not acting as a WFD Sink with an integrated display is not connected to an external display RULE wfd-idr-request wfd-idr-request = “wfd_idr_request” CRLF RTSP Methods OPTIONS org.wfa.wfd1.0 SET_PARAMETER GET_PARAMETER SETUP PLAY TEARDOWN PAUSE RULE RTSP SETUP Transport = “Transport:” SP profile port-numbers CRLF profile = “RTP/AVP/UDP;unicast;” port-numbers = client-port [“;” server-port]; client-port only at M6 request message, (client-port “;” server- port) at M6 response message. client-port = “client_port=” (rtp-port0 / rtp-port1) [“-” IPPORT]; rtp-port0 from a Primary Sink, rtp-port1 from a Secondary Sink. IPPORT here is rtp-port0 (or rtp-port1) plus 1 to be used for RTCP. [“-” IPPORT] can only appear in M6 request if the WFD Sink wants to use optional RTCP. [“-” IPPORT] can only appear in M6 response if the WFD Source accepts to use optional RTCP. server-port = “server_port=” IPPORT [“-” IPPORT]; server’s UDP port number for RTP. Optional IPPORT is server’s UDP port number for RTP plus 1 to be used for optional RTCP. [“-” IPPORT] can only appear in M6 response if the WFD Source accepts to use optional RTCP. /////////////////////////////////////////////////////////////////////////////// // Payload /////////////////////////////////////////////////////////////////////////////// wfd-audio-codecs wfd-video-formats wfd-3d-formats wfd-content-protection wfd-display-edid wfd-coupled-sink wfd-trigger-method wfd-presentation-url wfd-client-rtp-ports wfd-route wfd-I2C wfd-av-format-change-timing wfd-preferred-display-mode wfd-uibc-capability wfd-uibc-setting wfd-standby-resume-capability wfd-standby wfd-connector-type wfd-idr-request /////////////////////////////////////////////////////////////////////////////// // Messages /////////////////////////////////////////////////////////////////////////////// M1 Request (src->snk) OPTIONS * RTSP/1.0 CSeq: i Require: org.wfa.wfd1.0 M1 Response (snk->src) RTSP/1.0 200 OK CSeq: i Date: Sun, Aug 21 2011 04:20:53 GMT Public: org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER ------------------------------------------------------------------------------- M2 Request (src->snk) OPTIONS * RTSP/1.0 CSeq: j Require: org.wfa.wfd1.0 M2 Response (snk->src) RTSP/1.0 200 OK CSeq: j Date: Sun, Aug 21 2011 04:20:53 GMT Public: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER ------------------------------------------------------------------------------- M3 Request (src->snk) GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: i+1 Content-Type: text/parameters Content-Length: 141 wfd_video_formats wfd_audio_codecs wfd_3d_video_formats wfd_content_protection wfd_display_edid wfd_coupled_sink wfd_client_rtp_ports M3 Response (snk->src) RTSP/1.0 200 OK CSeq: i+1 Content-Length: 290 Content-Type: text/parameters wfd_video_formats: 00 00 00 01 01 00000001 00000000 00000000 000000 0000 00 none none wfd_audio_codecs: LPCM 00000003 00 wfd_3d_video_formats: none wfd_content_protection: none wfd_display_edid: none wfd_coupled_sink: none wfd_client_rtp_ports: RTP/AVP/UDP;unicast 1028 0 mode=play ------------------------------------------------------------------------------- M4 ------------------------------------------------------------------------------- M5 ------------------------------------------------------------------------------- M6 ================================================ FILE: libwds/rtsp/options.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/options.h" namespace wds { namespace rtsp { Options::Options(const std::string& request_uri) : Request(Request::MethodOptions, request_uri) { } Options::~Options() { } std::string Options::ToString() const { std::string ret = MethodName::OPTIONS + std::string(SPACE) + request_uri() + std::string(SPACE) + std::string(RTSP_END) + std::string(CRLF); return ret + Message::ToString(); } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/options.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_OPTIONS_H_ #define LIBWDS_RTSP_OPTIONS_H_ #include "libwds/rtsp/message.h" namespace wds { namespace rtsp { class Options: public Request { public: explicit Options(const std::string& request_uri); ~Options() override; std::string ToString() const override; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_OPTIONS_H_ ================================================ FILE: libwds/rtsp/parser.ypp ================================================ %pure-parser %no-lines %output "gen/parser.cpp" %defines "gen/parser.h" %code requires { /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include "libwds/rtsp/audiocodecs.h" #include "libwds/rtsp/contentprotection.h" #include "libwds/rtsp/triggermethod.h" #include "libwds/rtsp/route.h" #include "libwds/rtsp/uibcsetting.h" #include "libwds/rtsp/uibccapability.h" #define YYLEX_PARAM scanner namespace wds { struct AudioCodec; namespace rtsp { class Driver; class Scanner; class Message; class Header; class TransportHeader; class Property; class PropertyErrors; class Payload; class VideoFormats; struct H264Codec; struct H264Codec3d; } } } %lex-param {void* scanner} { std::unique_ptr& message } %parse-param {void* scanner} { std::unique_ptr& message } %code { #include #include #include #include #include #include "libwds/rtsp/driver.h" #include "libwds/rtsp/message.h" #include "libwds/rtsp/header.h" #include "libwds/rtsp/transportheader.h" #include "libwds/rtsp/payload.h" #include "libwds/rtsp/reply.h" #include "libwds/rtsp/options.h" #include "libwds/rtsp/getparameter.h" #include "libwds/rtsp/setparameter.h" #include "libwds/rtsp/play.h" #include "libwds/rtsp/teardown.h" #include "libwds/rtsp/pause.h" #include "libwds/rtsp/setup.h" #include "libwds/rtsp/audiocodecs.h" #include "libwds/rtsp/videoformats.h" #include "libwds/rtsp/formats3d.h" #include "libwds/rtsp/contentprotection.h" #include "libwds/rtsp/displayedid.h" #include "libwds/rtsp/coupledsink.h" #include "libwds/rtsp/triggermethod.h" #include "libwds/rtsp/clientrtpports.h" #include "libwds/rtsp/i2c.h" #include "libwds/rtsp/avformatchangetiming.h" #include "libwds/rtsp/standbyresumecapability.h" #include "libwds/rtsp/standby.h" #include "libwds/rtsp/idrrequest.h" #include "libwds/rtsp/connectortype.h" #include "libwds/rtsp/preferreddisplaymode.h" #include "libwds/rtsp/presentationurl.h" #include "libwds/rtsp/uibccapability.h" #define UNUSED_TOKEN(T) (void)T #define DELETE_TOKEN(T) \ delete T; \ T = nullptr } %union { std::string* sval; unsigned long long int nval; bool bool_val; std::vector* vsval; wds::rtsp::Message* message; wds::rtsp::Header* header; wds::rtsp::Payload* mpayload; wds::AudioFormats audio_format; wds::rtsp::Property* property; std::vector* error_list; wds::rtsp::PropertyErrors* property_errors; std::map>* property_error_map; std::vector* codecs; wds::rtsp::H264Codec* codec; std::vector* codecs_3d; wds::rtsp::H264Codec3d* codec_3d; wds::rtsp::ContentProtection::HDCPSpec hdcp_spec; wds::rtsp::TriggerMethod::Method trigger_method; wds::rtsp::Route::Destination route_destination; bool uibc_setting; std::vector* input_category_list; std::vector* generic_cap_list; std::vector* hidc_cap_list; wds::rtsp::UIBCCapability::InputCategory input_category_list_value; wds::rtsp::UIBCCapability::InputType generic_cap_list_value; wds::rtsp::UIBCCapability::DetailedCapability* hidc_cap_list_value; wds::rtsp::UIBCCapability::InputPath input_path; wds::rtsp::Method method; std::vector* methods; wds::rtsp::PropertyType parameter; std::vector* parameters; std::vector* audio_codecs; wds::AudioCodec* audio_codec; std::pair* session_info; wds::rtsp::TransportHeader* transport; } %token END 0 %token WFD_SP %token WFD_NUM %token WFD_OPTIONS %token WFD_SET_PARAMETER %token WFD_GET_PARAMETER %token WFD_SETUP %token WFD_PLAY %token WFD_TEARDOWN %token WFD_PAUSE %token WFD_END %token WFD_RESPONSE %token WFD_RESPONSE_CODE %token WFD_STRING %token WFD_GENERIC_PROPERTY %token WFD_HEADER %token WFD_CSEQ %token WFD_RESPONSE_METHODS %token WFD_TAG %token WFD_SUPPORT_CHECK %token WFD_REQUEST_URI %token WFD_CONTENT_TYPE %token WFD_MIME %token WFD_CONTENT_LENGTH %token WFD_AUDIO_CODECS %token WFD_VIDEO_FORMATS %token WFD_3D_FORMATS %token WFD_CONTENT_PROTECTION %token WFD_DISPLAY_EDID %token WFD_COUPLED_SINK %token WFD_TRIGGER_METHOD %token WFD_PRESENTATION_URL %token WFD_CLIENT_RTP_PORTS %token WFD_ROUTE %token WFD_I2C %token WFD_AV_FORMAT_CHANGE_TIMING %token WFD_PREFERRED_DISPLAY_MODE %token WFD_UIBC_CAPABILITY %token WFD_UIBC_SETTING %token WFD_STANDBY_RESUME_CAPABILITY %token WFD_STANDBY_IN_REQUEST %token WFD_STANDBY_IN_RESPONSE %token WFD_CONNECTOR_TYPE %token WFD_IDR_REQUEST %token WFD_AUDIO_CODECS_ERROR %token WFD_VIDEO_FORMATS_ERROR %token WFD_3D_FORMATS_ERROR %token WFD_CONTENT_PROTECTION_ERROR %token WFD_DISPLAY_EDID_ERROR %token WFD_COUPLED_SINK_ERROR %token WFD_TRIGGER_METHOD_ERROR %token WFD_PRESENTATION_URL_ERROR %token WFD_CLIENT_RTP_PORTS_ERROR %token WFD_ROUTE_ERROR %token WFD_I2C_ERROR %token WFD_AV_FORMAT_CHANGE_TIMING_ERROR %token WFD_PREFERRED_DISPLAY_MODE_ERROR %token WFD_UIBC_CAPABILITY_ERROR %token WFD_UIBC_SETTING_ERROR %token WFD_STANDBY_RESUME_CAPABILITY_ERROR %token WFD_STANDBY_ERROR %token WFD_CONNECTOR_TYPE_ERROR %token WFD_IDR_REQUEST_ERROR %token WFD_GENERIC_PROPERTY_ERROR %token WFD_NONE %token WFD_AUDIO_CODEC_LPCM %token WFD_AUDIO_CODEC_AAC %token WFD_AUDIO_CODEC_AC3 %token WFD_HDCP_SPEC_2_0 %token WFD_HDCP_SPEC_2_1 %token WFD_IP_PORT %token WFD_PRESENTATION_URL_0 %token WFD_PRESENTATION_URL_1 %token WFD_STREAM_PROFILE %token WFD_MODE_PLAY %token WFD_ROUTE_PRIMARY %token WFD_ROUTE_SECONDARY %token WFD_INPUT_CATEGORY_LIST %token WFD_INPUT_CATEGORY_GENERIC %token WFD_INPUT_CATEGORY_HIDC %token WFD_GENERIC_CAP_LIST %token WFD_INPUT_TYPE_KEYBOARD %token WFD_INPUT_TYPE_MOUSE %token WFD_INPUT_TYPE_SINGLE_TOUCH %token WFD_INPUT_TYPE_MULTI_TOUCH %token WFD_INPUT_TYPE_JOYSTICK %token WFD_INPUT_TYPE_CAMERA %token WFD_INPUT_TYPE_GESTURE %token WFD_INPUT_TYPE_REMOTE_CONTROL %token WFD_HIDC_CAP_LIST %token WFD_INPUT_PATH_INFRARED %token WFD_INPUT_PATH_USB %token WFD_INPUT_PATH_BT %token WFD_INPUT_PATH_WIFI %token WFD_INPUT_PATH_ZIGBEE %token WFD_INPUT_PATH_NOSP %token WFD_UIBC_SETTING_ENABLE %token WFD_UIBC_SETTING_DISABLE %token WFD_SUPPORTED %token WFD_SESSION %token WFD_SESSION_ID %token WFD_TIMEOUT %token WFD_TRANSPORT %token WFD_SERVER_PORT %type options set_parameter get_parameter setup play teardown pause %type wfd_reply command %type
headers %type wfd_content_type %type wfd_session %type wfd_method %type wfd_methods wfd_supported_methods %type wfd_content_length %type wfd_cseq %type wfd_audio_codec_type %type wfd_property wfd_property_audio_codecs %type wfd_property_video_formats %type wfd_property_3d_formats %type wfd_content_protection %type wfd_display_edid %type wfd_coupled_sink %type wfd_trigger_method %type wfd_presentation_url %type wfd_client_rtp_ports %type wfd_route %type wfd_I2C %type wfd_av_format_change_timing %type wfd_preferred_display_mode %type wfd_uibc_capability %type wfd_uibc_setting %type wfd_standby_resume_capability %type wfd_connector_type %type wdf_property_map %type wfd_property_error_map %type wfd_property_errors %type wfd_error_list %type payload %type wfd_h264_codecs %type wfd_h264_codec %type wfd_max_hres %type wfd_max_vres %type wfd_h264_codecs_3d %type wfd_h264_codec_3d %type hdcp2_spec %type wfd_edid_payload %type wfd_sink_address %type wfd_supported_trigger_methods %type wfd_route_destination %type wfd_port %type wfd_uibc_setting_value %type wfd_standby_resume_capability_value %type wfd_presentation_url0 wfd_presentation_url1 %type wfd_input_category_list wfd_input_category_list_values %type wfd_generic_cap_list wfd_generic_cap_list_values %type wfd_hidc_cap_list wfd_hidc_cap_list_values %type wfd_input_category_list_value %type wfd_generic_cap_list_value %type wfd_hidc_cap_list_value %type wfd_input_path %type wfd_parameter %type wfd_parameter_list %type wfd_audio_codec_list %type wfd_audio_codec %type wfd_transport %destructor { DELETE_TOKEN($$); } WFD_STRING WFD_REQUEST_URI WFD_MIME WFD_GENERIC_PROPERTY %destructor { DELETE_TOKEN($$); } wfd_methods wfd_supported_methods %destructor { DELETE_TOKEN($$); } wfd_h264_codec wfd_h264_codecs %destructor { DELETE_TOKEN($$); } wfd_h264_codec_3d wfd_h264_codecs_3d %destructor { DELETE_TOKEN($$); } wfd_edid_payload %destructor { DELETE_TOKEN($$); } wfd_hidc_cap_list_value %destructor { DELETE_TOKEN($$); } wfd_parameter_list %destructor { DELETE_TOKEN($$); } wfd_audio_codec wfd_audio_codec_list %% start: message ; message: command headers { message.reset($1); $1->set_header(std::unique_ptr($2)); } | payload { if (message && $1) message->set_payload(std::unique_ptr($1)); else YYERROR; } | error { message.reset(); std::cerr << "Unknown message" << std::endl; YYABORT; } ; command: options | set_parameter | get_parameter | setup | play | teardown | pause | wfd_reply ; options: WFD_OPTIONS WFD_SP '*' WFD_SP WFD_END { $$ = new wds::rtsp::Options("*"); } | WFD_OPTIONS WFD_SP WFD_REQUEST_URI WFD_SP WFD_END { $$ = new wds::rtsp::Options(*$3); DELETE_TOKEN($3); } ; set_parameter: WFD_SET_PARAMETER WFD_SP WFD_REQUEST_URI WFD_SP WFD_END { $$ = new wds::rtsp::SetParameter(*$3); DELETE_TOKEN($3); } ; get_parameter: WFD_GET_PARAMETER WFD_SP WFD_REQUEST_URI WFD_SP WFD_END { $$ = new wds::rtsp::GetParameter(*$3); DELETE_TOKEN($3); } ; setup: WFD_SETUP WFD_SP WFD_REQUEST_URI WFD_SP WFD_END { $$ = new wds::rtsp::Setup(*$3); DELETE_TOKEN($3); } ; play: WFD_PLAY WFD_SP WFD_REQUEST_URI WFD_SP WFD_END { $$ = new wds::rtsp::Play(*$3); DELETE_TOKEN($3); } ; teardown: WFD_TEARDOWN WFD_SP WFD_REQUEST_URI WFD_SP WFD_END { $$ = new wds::rtsp::Teardown(*$3); DELETE_TOKEN($3); } ; pause: WFD_PAUSE WFD_SP WFD_REQUEST_URI WFD_SP WFD_END { $$ = new wds::rtsp::Pause(*$3); DELETE_TOKEN($3); } ; wfd_reply: WFD_RESPONSE WFD_RESPONSE_CODE WFD_STRING { DELETE_TOKEN($3); $$ = new wds::rtsp::Reply($2); } ; headers: { $$ = new wds::rtsp::Header(); } | headers wfd_cseq { $1->set_cseq($2); } | headers WFD_SUPPORT_CHECK { $1->set_require_wfd_support(true); } | headers wfd_content_type { $1->set_content_type(*$2); DELETE_TOKEN($2); } | headers wfd_content_length { $1->set_content_length($2); } | headers wfd_supported_methods { $1->set_supported_methods(*$2); DELETE_TOKEN($2); } | headers wfd_session { $1->set_session((*$2).first); $1->set_timeout((*$2).second); DELETE_TOKEN($2); } | headers wfd_transport { $1->set_transport ($2); } | headers WFD_HEADER wfd_ows WFD_STRING { $1->add_generic_header(*$2, *$4); DELETE_TOKEN($2); DELETE_TOKEN($4); } ; wfd_cseq: WFD_CSEQ wfd_ows WFD_NUM { $$ = $3; } ; wfd_content_type: WFD_CONTENT_TYPE wfd_ows WFD_MIME { $$ = $3; } ; wfd_content_length: WFD_CONTENT_LENGTH wfd_ows WFD_NUM { $$ = $3; } ; wfd_session: WFD_SESSION WFD_SP WFD_SESSION_ID { $$ = new std::pair(*$3, 0); DELETE_TOKEN($3); } | WFD_SESSION WFD_SP WFD_SESSION_ID WFD_TIMEOUT WFD_NUM { $$ = new std::pair(*$3, $5); DELETE_TOKEN($3); } ; wfd_transport: WFD_TRANSPORT WFD_NUM { $$ = new wds::rtsp::TransportHeader(); $$->set_client_port ($2); } | WFD_TRANSPORT WFD_NUM '-' WFD_NUM { $$ = new wds::rtsp::TransportHeader(); $$->set_client_port ($2); $$->set_client_supports_rtcp (true); } | WFD_TRANSPORT WFD_NUM WFD_SERVER_PORT WFD_NUM { $$ = new wds::rtsp::TransportHeader(); $$->set_client_port ($2); $$->set_server_port ($4); } | WFD_TRANSPORT WFD_NUM '-' WFD_NUM WFD_SERVER_PORT WFD_NUM { $$ = new wds::rtsp::TransportHeader(); $$->set_client_port ($2); $$->set_client_supports_rtcp (true); $$->set_server_port ($6); } | WFD_TRANSPORT WFD_NUM WFD_SERVER_PORT WFD_NUM '-' WFD_NUM { $$ = new wds::rtsp::TransportHeader(); $$->set_client_port ($2); $$->set_server_port ($4); $$->set_server_supports_rtcp (true); } | WFD_TRANSPORT WFD_NUM '-' WFD_NUM WFD_SERVER_PORT WFD_NUM '-' WFD_NUM { $$ = new wds::rtsp::TransportHeader(); $$->set_client_port ($2); $$->set_client_supports_rtcp (true); $$->set_server_port ($6); $$->set_server_supports_rtcp (true); } ; wfd_supported_methods: WFD_RESPONSE_METHODS wfd_ows wfd_methods { $$ = $3; } ; wfd_methods: wfd_method { $$ = new std::vector(); $$->push_back($1); } | wfd_methods wfd_ows ',' wfd_ows wfd_method { UNUSED_TOKEN($$); $1->push_back($5); } ; wfd_method: WFD_OPTIONS { $$ = wds::rtsp::OPTIONS; } | WFD_SET_PARAMETER { $$ = wds::rtsp::SET_PARAMETER; } | WFD_GET_PARAMETER { $$ = wds::rtsp::GET_PARAMETER; } | WFD_SETUP { $$ = wds::rtsp::SETUP; } | WFD_PLAY { $$ = wds::rtsp::PLAY; } | WFD_TEARDOWN { $$ = wds::rtsp::TEARDOWN; } | WFD_PAUSE { $$ = wds::rtsp::PAUSE; } | WFD_TAG { $$ = wds::rtsp::ORG_WFA_WFD_1_0; } ; wfd_ows: /*blank*/ | WFD_SP ; payload: { $$ = 0; } | wfd_parameter_list | wdf_property_map | wfd_property_error_map ; /* used for GET_PARAMETER method */ wfd_parameter_list: wfd_parameter_list wfd_parameter { UNUSED_TOKEN($$); if (auto payload = ToGetParameterPayload($1)) payload->AddRequestProperty($2); else YYERROR; } | wfd_parameter { $$ = new wds::rtsp::GetParameterPayload(); wds::rtsp::ToGetParameterPayload($$)->AddRequestProperty($1); } | wfd_parameter_list WFD_GENERIC_PROPERTY { UNUSED_TOKEN($$); if (auto payload = ToGetParameterPayload($1)) payload->AddRequestProperty(*$2); else YYERROR; DELETE_TOKEN($2); } | WFD_GENERIC_PROPERTY { $$ = new wds::rtsp::GetParameterPayload(); wds::rtsp::ToGetParameterPayload($$)->AddRequestProperty(*$1); DELETE_TOKEN($1); } ; wfd_parameter: WFD_AUDIO_CODECS { $$ = wds::rtsp::AudioCodecsPropertyType; } | WFD_VIDEO_FORMATS { $$ = wds::rtsp::VideoFormatsPropertyType; } | WFD_3D_FORMATS { $$ = wds::rtsp::Video3DFormatsPropertyType; } | WFD_CONTENT_PROTECTION { $$ = wds::rtsp::ContentProtectionPropertyType; } | WFD_DISPLAY_EDID { $$ = wds::rtsp::DisplayEdidPropertyType; } | WFD_COUPLED_SINK { $$ = wds::rtsp::CoupledSinkPropertyType; } | WFD_TRIGGER_METHOD { $$ = wds::rtsp::TriggerMethodPropertyType; } | WFD_PRESENTATION_URL { $$ = wds::rtsp::PresentationURLPropertyType; } | WFD_CLIENT_RTP_PORTS { $$ = wds::rtsp::ClientRTPPortsPropertyType; } | WFD_ROUTE { $$ = wds::rtsp::RoutePropertyType; } | WFD_I2C { $$ = wds::rtsp::I2CPropertyType; } | WFD_AV_FORMAT_CHANGE_TIMING { $$ = wds::rtsp::AVFormatChangeTimingPropertyType; } | WFD_PREFERRED_DISPLAY_MODE { $$ = wds::rtsp::PreferredDisplayModePropertyType; } | WFD_UIBC_CAPABILITY { $$ = wds::rtsp::UIBCCapabilityPropertyType; } | WFD_UIBC_SETTING { $$ = wds::rtsp::UIBCSettingPropertyType; } | WFD_STANDBY_RESUME_CAPABILITY { $$ = wds::rtsp::StandbyResumeCapabilityPropertyType; } | WFD_STANDBY_IN_REQUEST { $$ = wds::rtsp::StandbyPropertyType; } | WFD_CONNECTOR_TYPE { $$ = wds::rtsp::ConnectorTypePropertyType; } ; wfd_error_list: WFD_NUM { $$ = new std::vector(); $$->push_back($1); } | wfd_error_list ',' WFD_SP WFD_NUM { $1->push_back($4); } wfd_property_errors: WFD_AUDIO_CODECS_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::AudioCodecsPropertyType, *$4); DELETE_TOKEN($4); } | WFD_VIDEO_FORMATS_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::VideoFormatsPropertyType, *$4); DELETE_TOKEN($4); } | WFD_3D_FORMATS_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::Video3DFormatsPropertyType, *$4); DELETE_TOKEN($4); } | WFD_CONTENT_PROTECTION_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::ContentProtectionPropertyType, *$4); DELETE_TOKEN($4); } | WFD_DISPLAY_EDID_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::DisplayEdidPropertyType, *$4); DELETE_TOKEN($4); } | WFD_COUPLED_SINK_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::CoupledSinkPropertyType, *$4); DELETE_TOKEN($4); } | WFD_TRIGGER_METHOD_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::TriggerMethodPropertyType, *$4); DELETE_TOKEN($4); } | WFD_PRESENTATION_URL_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::PresentationURLPropertyType, *$4); DELETE_TOKEN($4); } | WFD_CLIENT_RTP_PORTS_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::ClientRTPPortsPropertyType, *$4); DELETE_TOKEN($4); } | WFD_ROUTE_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::RoutePropertyType, *$4); DELETE_TOKEN($4); } | WFD_I2C_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::I2CPropertyType, *$4); DELETE_TOKEN($4); } | WFD_AV_FORMAT_CHANGE_TIMING_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::AVFormatChangeTimingPropertyType, *$4); DELETE_TOKEN($4); } | WFD_PREFERRED_DISPLAY_MODE_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::PreferredDisplayModePropertyType, *$4); DELETE_TOKEN($4); } | WFD_UIBC_CAPABILITY_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::UIBCCapabilityPropertyType, *$4); DELETE_TOKEN($4); } | WFD_UIBC_SETTING_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::UIBCSettingPropertyType, *$4); DELETE_TOKEN($4); } | WFD_STANDBY_RESUME_CAPABILITY_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::StandbyResumeCapabilityPropertyType, *$4); DELETE_TOKEN($4); } | WFD_CONNECTOR_TYPE_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::ConnectorTypePropertyType, *$4); DELETE_TOKEN($4); } | WFD_IDR_REQUEST_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(wds::rtsp::IDRRequestPropertyType, *$4); DELETE_TOKEN($4); } | WFD_GENERIC_PROPERTY_ERROR ':' WFD_SP wfd_error_list { $$ = new wds::rtsp::PropertyErrors(*$1, *$4); DELETE_TOKEN($1); DELETE_TOKEN($4); } ; wfd_property_error_map: wfd_property_errors { $$ = new wds::rtsp::PropertyErrorPayload(); ToPropertyErrorPayload($$)->AddPropertyError(std::shared_ptr($1)); } | wfd_property_error_map wfd_property_errors { if (auto payload = ToPropertyErrorPayload($1)) payload->AddPropertyError(std::shared_ptr($2)); else YYERROR; } ; wdf_property_map: wfd_property { $$ = new wds::rtsp::PropertyMapPayload(); ToPropertyMapPayload($$)->AddProperty(std::shared_ptr($1)); } | wdf_property_map wfd_property { if (auto payload = ToPropertyMapPayload($1)) payload->AddProperty(std::shared_ptr($2)); else YYERROR; } ; wfd_property: wfd_property_audio_codecs | wfd_property_video_formats | wfd_property_3d_formats | wfd_content_protection | wfd_display_edid | wfd_coupled_sink | wfd_trigger_method | wfd_presentation_url | wfd_client_rtp_ports | wfd_route | wfd_I2C | wfd_av_format_change_timing | wfd_preferred_display_mode | wfd_uibc_capability | wfd_uibc_setting | wfd_standby_resume_capability | wfd_connector_type | WFD_STANDBY_IN_RESPONSE { $$ = new wds::rtsp::Standby(); } | WFD_IDR_REQUEST { $$ = new wds::rtsp::IDRRequest(); } | WFD_GENERIC_PROPERTY WFD_STRING { $$ = new wds::rtsp::GenericProperty(*$1, *$2); DELETE_TOKEN($1); DELETE_TOKEN($2); } ; wfd_property_audio_codecs: WFD_AUDIO_CODECS ':' WFD_SP wfd_audio_codec_list { $$ = new wds::rtsp::AudioCodecs(*$4); DELETE_TOKEN($4); } | WFD_AUDIO_CODECS ':' WFD_SP WFD_NONE { $$ = new wds::rtsp::AudioCodecs(); } ; wfd_audio_codec_list: wfd_audio_codec { $$ = new std::vector(); $$->push_back(*$1); DELETE_TOKEN($1); } | wfd_audio_codec_list ',' WFD_SP wfd_audio_codec { UNUSED_TOKEN($$); $1->push_back(*$4); DELETE_TOKEN($4); } ; wfd_audio_codec: wfd_audio_codec_type WFD_SP WFD_NUM WFD_SP WFD_NUM { $$ = new wds::AudioCodec($1, $3, $5); } ; wfd_audio_codec_type: WFD_AUDIO_CODEC_LPCM { $$ = wds::LPCM; } | WFD_AUDIO_CODEC_AAC { $$ = wds::AAC; } | WFD_AUDIO_CODEC_AC3 { $$ = wds::AC3; } ; wfd_property_video_formats: WFD_VIDEO_FORMATS ':' wfd_ows WFD_NONE { $$ = new wds::rtsp::VideoFormats(); } /* native, preferred-display-mode-supported, H.264-codecs */ | WFD_VIDEO_FORMATS ':' wfd_ows WFD_NUM WFD_SP WFD_NUM WFD_SP wfd_h264_codecs { $$ = new wds::rtsp::VideoFormats($4, $6, *$8); DELETE_TOKEN($8); } ; wfd_h264_codecs: wfd_h264_codec { $$ = new wds::rtsp::H264Codecs(); $$->push_back(*$1); DELETE_TOKEN($1); } | wfd_h264_codecs wfd_ows ',' wfd_ows wfd_h264_codec { UNUSED_TOKEN($$); $1->push_back(*$5); DELETE_TOKEN($5); } ; wfd_h264_codec: /* profile, level, misc-params , max-hres, max-vres */ WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP wfd_max_hres WFD_SP wfd_max_vres { $$ = new wds::rtsp::H264Codec($1, $3, $5, $7, $9, $11, $13, $15, $17, $19, $21); } wfd_h264_codecs_3d: wfd_h264_codec_3d { $$ = new wds::rtsp::H264Codecs3d(); $$->push_back(*$1); DELETE_TOKEN($1); } | wfd_h264_codecs_3d wfd_ows ',' wfd_ows wfd_h264_codec_3d { UNUSED_TOKEN($$); $1->push_back(*$5); DELETE_TOKEN($5); } ; wfd_h264_codec_3d: WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP wfd_max_hres WFD_SP wfd_max_vres { $$ = new wds::rtsp::H264Codec3d($1, $3, $5, $7, $9, $11, $13, $15, $17); } ; wfd_max_hres: WFD_NONE { $$ = 0; } | WFD_NUM ; wfd_max_vres: WFD_NONE { $$ = 0; } | WFD_NUM ; wfd_property_3d_formats: /* native, preferred-display-mode-supported, H.264-codecs */ WFD_3D_FORMATS ':' WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP wfd_h264_codecs_3d { $$ = new wds::rtsp::Formats3d($4, $6, *$8); DELETE_TOKEN($8); } | WFD_3D_FORMATS ':' WFD_SP WFD_NONE { $$ = new wds::rtsp::Formats3d(); } ; wfd_content_protection: WFD_CONTENT_PROTECTION ':' WFD_SP WFD_NONE { $$ = new wds::rtsp::ContentProtection(); } | WFD_CONTENT_PROTECTION ':' WFD_SP hdcp2_spec WFD_SP WFD_IP_PORT WFD_NUM { $$ = new wds::rtsp::ContentProtection($4, $7); } ; hdcp2_spec: WFD_HDCP_SPEC_2_0 { $$ = wds::rtsp::ContentProtection::HDCP_SPEC_2_0; } | WFD_HDCP_SPEC_2_1 { $$ = wds::rtsp::ContentProtection::HDCP_SPEC_2_1; } ; wfd_display_edid: WFD_DISPLAY_EDID ':' WFD_SP WFD_NONE { $$ = new wds::rtsp::DisplayEdid(); } | WFD_DISPLAY_EDID ':' WFD_SP WFD_NUM WFD_SP wfd_edid_payload { $$ = new wds::rtsp::DisplayEdid($4, $6 ? *$6 : ""); DELETE_TOKEN($6); } ; wfd_edid_payload: WFD_NONE { $$ = 0; } | WFD_STRING ; wfd_coupled_sink: WFD_COUPLED_SINK ':' WFD_SP WFD_NONE { $$ = new wds::rtsp::CoupledSink(); } | WFD_COUPLED_SINK ':' WFD_SP WFD_NUM WFD_SP wfd_sink_address { $$ = new wds::rtsp::CoupledSink($4, $6); } ; wfd_sink_address: WFD_NONE { $$ = -1; } | WFD_NUM ; wfd_trigger_method: WFD_TRIGGER_METHOD ':' WFD_SP wfd_supported_trigger_methods { $$ = new wds::rtsp::TriggerMethod($4); } ; wfd_supported_trigger_methods: WFD_SETUP { $$ = wds::rtsp::TriggerMethod::SETUP; } | WFD_PAUSE{ $$ = wds::rtsp::TriggerMethod::PAUSE; } | WFD_TEARDOWN { $$ = wds::rtsp::TriggerMethod::TEARDOWN; } | WFD_PLAY { $$ = wds::rtsp::TriggerMethod::PLAY; } ; wfd_presentation_url: WFD_PRESENTATION_URL ':' WFD_SP wfd_presentation_url0 WFD_SP wfd_presentation_url1 { $$ = new wds::rtsp::PresentationUrl($4 ? *$4 : "", $6 ? *$6 : ""); DELETE_TOKEN($4); DELETE_TOKEN($6); } ; wfd_presentation_url0: WFD_NONE { $$ = 0; } | WFD_PRESENTATION_URL_0 ; wfd_presentation_url1: WFD_NONE { $$ = 0; } | WFD_PRESENTATION_URL_1 ; wfd_client_rtp_ports: WFD_CLIENT_RTP_PORTS ':' WFD_SP WFD_STREAM_PROFILE WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_MODE_PLAY { $$ = new wds::rtsp::ClientRtpPorts($6, $8); } wfd_route: WFD_ROUTE ':' WFD_SP wfd_route_destination { $$ = new wds::rtsp::Route($4); } ; wfd_route_destination: WFD_ROUTE_PRIMARY { $$ = wds::rtsp::Route::PRIMARY; } | WFD_ROUTE_SECONDARY { $$ = wds::rtsp::Route::SECONDARY; } ; wfd_I2C: WFD_I2C ':' WFD_SP wfd_port { $$ = new wds::rtsp::I2C($4); } ; wfd_port: WFD_NONE { $$ = -1; } | WFD_NUM ; wfd_av_format_change_timing: WFD_AV_FORMAT_CHANGE_TIMING ':' WFD_SP WFD_NUM WFD_SP WFD_NUM { $$ = new wds::rtsp::AVFormatChangeTiming($4, $6); } ; wfd_preferred_display_mode: /* p-clock SP H SP HB SP HSPOL-HSOFF SP HSW SP V SP VB SP VSPOL-VSOFF SP VSW SP VBS3D SP 2d-s3d-modes SP p-depth SP H.264-codec */ WFD_PREFERRED_DISPLAY_MODE ':' WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP WFD_NUM WFD_SP wfd_h264_codec { $$ = new wds::rtsp::PreferredDisplayMode($4, $6, $8, $10, $12, $14, $16, $18, $20, $22, $24, $26, *$28); DELETE_TOKEN($28); } ; wfd_uibc_capability: WFD_UIBC_CAPABILITY ':' WFD_SP WFD_NONE { $$ = new wds::rtsp::UIBCCapability(); } | WFD_UIBC_CAPABILITY ':' WFD_SP wfd_input_category_list ';' wfd_generic_cap_list ';' wfd_hidc_cap_list ';' WFD_IP_PORT wfd_port { $$ = new wds::rtsp::UIBCCapability(*$4, *$6, *$8, $11); DELETE_TOKEN($4); DELETE_TOKEN($6); DELETE_TOKEN($8); } ; wfd_input_category_list: WFD_INPUT_CATEGORY_LIST wfd_input_category_list_values { $$ = $2; } ; wfd_input_category_list_values: WFD_NONE { $$ = new std::vector(); } | wfd_input_category_list_value { $$ = new std::vector(); $$->push_back($1); } | wfd_input_category_list_values ',' WFD_SP wfd_input_category_list_value { $1->push_back($4); } ; wfd_input_category_list_value: WFD_INPUT_CATEGORY_GENERIC { $$ = wds::rtsp::UIBCCapability::GENERIC; } | WFD_INPUT_CATEGORY_HIDC { $$ = wds::rtsp::UIBCCapability::HIDC; } ; wfd_generic_cap_list: WFD_GENERIC_CAP_LIST wfd_generic_cap_list_values { $$ = $2; } ; wfd_generic_cap_list_values: WFD_NONE { $$ = new std::vector(); } | wfd_generic_cap_list_value { $$ = new std::vector(); $$->push_back($1); } | wfd_generic_cap_list_values ',' WFD_SP wfd_generic_cap_list_value { $1->push_back($4); } ; wfd_generic_cap_list_value: WFD_INPUT_TYPE_KEYBOARD { $$ = wds::rtsp::UIBCCapability::KEYBOARD; } | WFD_INPUT_TYPE_MOUSE { $$ = wds::rtsp::UIBCCapability::MOUSE; } | WFD_INPUT_TYPE_SINGLE_TOUCH { $$ = wds::rtsp::UIBCCapability::SINGLE_TOUCH; } | WFD_INPUT_TYPE_MULTI_TOUCH { $$ = wds::rtsp::UIBCCapability::MULTI_TOUCH; } | WFD_INPUT_TYPE_JOYSTICK { $$ = wds::rtsp::UIBCCapability::JOYSTICK; } | WFD_INPUT_TYPE_CAMERA { $$ = wds::rtsp::UIBCCapability::CAMERA; } | WFD_INPUT_TYPE_GESTURE { $$ = wds::rtsp::UIBCCapability::GESTURE; } | WFD_INPUT_TYPE_REMOTE_CONTROL { $$ = wds::rtsp::UIBCCapability::REMOTE_CONTROL; } ; wfd_hidc_cap_list: WFD_HIDC_CAP_LIST wfd_hidc_cap_list_values { $$ = $2; } ; wfd_hidc_cap_list_values: WFD_NONE { $$ = new std::vector(); } | wfd_hidc_cap_list_value { $$ = new std::vector(); $$->push_back(*$1); DELETE_TOKEN($1); } | wfd_hidc_cap_list_values ',' WFD_SP wfd_hidc_cap_list_value { $1->push_back(*$4); DELETE_TOKEN($4); } ; wfd_hidc_cap_list_value: wfd_generic_cap_list_value '/' wfd_input_path { $$ = new wds::rtsp::UIBCCapability::DetailedCapability($1, $3); } ; wfd_input_path: WFD_INPUT_PATH_INFRARED { $$ = wds::rtsp::UIBCCapability::INFRARED; } | WFD_INPUT_PATH_USB { $$ = wds::rtsp::UIBCCapability::USB; } | WFD_INPUT_PATH_BT { $$ = wds::rtsp::UIBCCapability::BT; } | WFD_INPUT_PATH_ZIGBEE { $$ = wds::rtsp::UIBCCapability::ZIGBEE; } | WFD_INPUT_PATH_WIFI { $$ = wds::rtsp::UIBCCapability::WI_FI; } | WFD_INPUT_PATH_NOSP { $$ = wds::rtsp::UIBCCapability::NO_SP; } ; wfd_uibc_setting: WFD_UIBC_SETTING ':' WFD_SP wfd_uibc_setting_value { $$ = new wds::rtsp::UIBCSetting($4); } ; wfd_uibc_setting_value: WFD_UIBC_SETTING_ENABLE { $$ = true; } | WFD_UIBC_SETTING_DISABLE { $$ = false; } ; wfd_standby_resume_capability: WFD_STANDBY_RESUME_CAPABILITY ':' WFD_SP wfd_standby_resume_capability_value { $$ = new wds::rtsp::StandbyResumeCapability($4); } ; wfd_standby_resume_capability_value: WFD_NONE { $$ = false; } | WFD_SUPPORTED { $$ = true; } ; wfd_connector_type: WFD_CONNECTOR_TYPE ':' WFD_SP WFD_NUM { $$ = new wds::rtsp::ConnectorType($4); } | WFD_CONNECTOR_TYPE ':' WFD_SP WFD_NONE { $$ = new wds::rtsp::ConnectorType(); } ; %% ================================================ FILE: libwds/rtsp/pause.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/pause.h" namespace wds { namespace rtsp { Pause::Pause(const std::string& request_uri) : Request(Request::MethodPause, request_uri) { } Pause::~Pause() { } std::string Pause::ToString() const { std::string ret = MethodName::PAUSE + std::string(SPACE) + request_uri() + std::string(SPACE) + std::string(RTSP_END) + std::string(CRLF); return ret + Message::ToString(); } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/pause.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_PAUSE_H_ #define LIBWDS_RTSP_PAUSE_H_ #include "libwds/rtsp/message.h" namespace wds { namespace rtsp { class Pause : public Request { public: explicit Pause(const std::string& request_uri); ~Pause() override; std::string ToString() const override; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_PAUSE_H_ ================================================ FILE: libwds/rtsp/payload.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/payload.h" namespace wds { namespace rtsp { Payload::~Payload() { } PropertyMapPayload::~PropertyMapPayload() { } std::shared_ptr PropertyMapPayload::GetProperty( const std::string& name) const { auto property = properties_.find(name); if (property != properties_.end()) return property->second; return nullptr; } std::shared_ptr PropertyMapPayload::GetProperty( PropertyType type) const { if (type == GenericPropertyType) return nullptr; return GetProperty(GetPropertyName(type)); } bool PropertyMapPayload::HasProperty(PropertyType type) const { return properties_.find(GetPropertyName(type)) != properties_.end(); } void PropertyMapPayload::AddProperty( const std::shared_ptr& property) { properties_[property->GetName()] = property; } std::string PropertyMapPayload::ToString() const { std::string ret; for (auto it : properties_) { if (auto property = it.second) { ret += property->ToString(); ret += "\r\n"; } } return ret; } GetParameterPayload::GetParameterPayload(const std::vector& properties) : Payload(Payload::Requests), properties_(properties) { } GetParameterPayload::~GetParameterPayload() { } void GetParameterPayload::AddRequestProperty(const PropertyType& type) { properties_.push_back(GetPropertyName(type)); } void GetParameterPayload::AddRequestProperty( const std::string& generic_property) { properties_.push_back(generic_property); } std::string GetParameterPayload::ToString() const { std::string ret; for (const std::string& property : properties_) { ret += property; ret += "\r\n"; } return ret; } PropertyErrorPayload::~PropertyErrorPayload() { } std::shared_ptr PropertyErrorPayload::GetPropertyError( const std::string& name) const { auto property = property_errors_.find(name); if (property != property_errors_.end()) return property->second; return nullptr; } std::shared_ptr PropertyErrorPayload::GetPropertyError( PropertyType type) const { if (type == GenericPropertyType) return nullptr; return GetPropertyError(GetPropertyName(type)); } void PropertyErrorPayload::AddPropertyError(const std::shared_ptr& errors) { if (errors->type() == GenericPropertyType) { property_errors_[errors->generic_property_name()] = errors; } else { property_errors_[GetPropertyName(errors->type())] = errors; } } std::string PropertyErrorPayload::ToString() const { std::string ret; for (auto it = property_errors_.rbegin(); it != property_errors_.rend(); ++it) { ret += it->second->ToString(); ret += "\r\n"; } return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/payload.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_PAYLOAD_H_ #define LIBWDS_RTSP_PAYLOAD_H_ #include #include #include #include #include "libwds/public/logging.h" #include "libwds/rtsp/property.h" #include "libwds/rtsp/genericproperty.h" #include "libwds/rtsp/propertyerrors.h" namespace wds { namespace rtsp { using PropertyMap = std::map>; using PropertyErrorMap = std::map>; class Payload { public: enum Type { Properties, Requests, Errors }; virtual ~Payload(); virtual std::string ToString() const = 0; Type type() const { return type_; } protected: explicit Payload(Type type) : type_(type) {} Type type_; }; class PropertyMapPayload : public Payload { public: PropertyMapPayload() : Payload(Payload::Properties) {} ~PropertyMapPayload() override; std::shared_ptr GetProperty(const std::string& name) const; std::shared_ptr GetProperty(PropertyType type) const; bool HasProperty(PropertyType type) const; void AddProperty(const std::shared_ptr& property); const PropertyMap& properties() const { return properties_; } std::string ToString() const override; private: PropertyMap properties_; }; inline PropertyMapPayload* ToPropertyMapPayload(Payload* payload) { if (!payload) return nullptr; if (payload->type() == Payload::Properties) return static_cast(payload); WDS_ERROR("Inappropriate payload type"); return nullptr; } class GetParameterPayload : public Payload { public: GetParameterPayload() : Payload(Payload::Requests) {} explicit GetParameterPayload( const std::vector& properties); ~GetParameterPayload() override; void AddRequestProperty(const PropertyType& property); void AddRequestProperty(const std::string& generic_property); const std::vector& properties() const { return properties_; } std::string ToString() const override; private: std::vector properties_; }; inline GetParameterPayload* ToGetParameterPayload(Payload* payload) { if (!payload) return nullptr; if (payload->type() == Payload::Requests) return static_cast(payload); WDS_ERROR("Inappropriate payload type"); return nullptr; } class PropertyErrorPayload : public Payload { public: PropertyErrorPayload() : Payload(Payload::Errors) {} ~PropertyErrorPayload() override; std::shared_ptr GetPropertyError(const std::string& name) const; std::shared_ptr GetPropertyError(PropertyType type) const; void AddPropertyError(const std::shared_ptr& error); const PropertyErrorMap& property_errors() const { return property_errors_; } std::string ToString() const override; private: PropertyErrorMap property_errors_; }; inline PropertyErrorPayload* ToPropertyErrorPayload(Payload* payload) { if (!payload) return nullptr; if (payload->type() == Payload::Errors) return static_cast(payload); WDS_ERROR("Inappropriate payload type"); return nullptr; } } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_PAYLOAD_H_ ================================================ FILE: libwds/rtsp/play.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/play.h" namespace wds { namespace rtsp { Play::Play(const std::string& request_uri) : Request(Request::MethodPlay, request_uri) { } std::string Play::ToString() const { std::string ret = MethodName::PLAY + std::string(SPACE) + request_uri() + std::string(SPACE) + std::string(RTSP_END) + std::string(CRLF); return ret + Message::ToString(); } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/play.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_PLAY_H_ #define LIBWDS_RTSP_PLAY_H_ #include "libwds/rtsp/message.h" namespace wds { namespace rtsp { class Play : public Request { public: explicit Play(const std::string& request_uri); std::string ToString() const override; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_PLAY_H_ ================================================ FILE: libwds/rtsp/preferreddisplaymode.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/preferreddisplaymode.h" #include "libwds/rtsp/macros.h" namespace wds { namespace rtsp { PreferredDisplayMode::PreferredDisplayMode( unsigned int p_clock,unsigned short h, unsigned short hb, unsigned short hspol_hsoff, unsigned short hsw, unsigned short v, unsigned short vb, unsigned short vspol_vsoff, unsigned short vsw, unsigned char vbs3d, unsigned char modes_2d_s3d, unsigned char p_depth, const H264Codec& h264_codec) : Property(PreferredDisplayModePropertyType), p_clock_(p_clock), h_(h), hb_(hb), hspol_hsoff_(hspol_hsoff), hsw_(hsw), v_(v), vb_(vb), vspol_vsoff_(vspol_vsoff), vsw_(vsw), vbs3d_(vbs3d), modes_2d_s3d_(modes_2d_s3d), p_depth_(p_depth), h264_codec_(h264_codec) { } std::string PreferredDisplayMode::ToString() const { MAKE_HEX_STRING_6(p_clock, p_clock_); MAKE_HEX_STRING_4(h, h_); MAKE_HEX_STRING_4(hb, hb_); MAKE_HEX_STRING_4(hspol_hsoff, hspol_hsoff_); MAKE_HEX_STRING_4(hsw, hsw_); MAKE_HEX_STRING_4(v, v_); MAKE_HEX_STRING_4(vb, vb_); MAKE_HEX_STRING_4(vspol_vsoff, vspol_vsoff_); MAKE_HEX_STRING_4(vsw, vsw_); MAKE_HEX_STRING_2(vbs3d, vbs3d_); MAKE_HEX_STRING_2(modes_2d_s3d, modes_2d_s3d_); MAKE_HEX_STRING_2(p_depth, p_depth_); std::string ret = PropertyName::wfd_preferred_display_mode + std::string(SEMICOLON) + std::string(SPACE) + p_clock + std::string(SPACE) + h + std::string(SPACE) + hb + std::string(SPACE) + hspol_hsoff + std::string(SPACE) + hsw + std::string(SPACE) + v + std::string(SPACE) + vb + std::string(SPACE) + vspol_vsoff + std::string(SPACE) + vsw + std::string(SPACE) + vbs3d + std::string(SPACE) + modes_2d_s3d + std::string(SPACE) + p_depth + std::string(SPACE) + h264_codec_.ToString(); return ret; } PreferredDisplayMode::~PreferredDisplayMode() { } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/preferreddisplaymode.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_PREFERREDDISPLAYMODE_H_ #define LIBWDS_RTSP_PREFERREDDISPLAYMODE_H_ #include "libwds/rtsp/property.h" #include "libwds/rtsp/videoformats.h" namespace wds { namespace rtsp { class PreferredDisplayMode: public Property { public: PreferredDisplayMode(unsigned int p_clock, unsigned short h, unsigned short hb, unsigned short hspol_hsoff, unsigned short hsw, unsigned short v, unsigned short vb, unsigned short vspol_vsoff, unsigned short vsw, unsigned char vbs3d, unsigned char modes_2d_s3d, unsigned char p_depth, const H264Codec& h264_codec); ~PreferredDisplayMode() override; unsigned int p_clock() const { return p_clock_; } unsigned short h() const { return h_; } unsigned short hb() const { return hb_; } unsigned short hspol_hsoff() const { return hspol_hsoff_; } unsigned short hsw() const { return hsw_; } unsigned short v() const { return v_; } unsigned short vb() const { return vb_; } unsigned short vspol_vsoff() const { return vspol_vsoff_; } unsigned short vsw() const { return vsw_; } unsigned char vbs3d() const { return vbs3d_; } unsigned char modes_2d_s3d() const { return modes_2d_s3d_; } unsigned char p_depth() const { return p_depth_; } const H264Codec& h264_codec() const { return h264_codec_; } std::string ToString() const override; private: unsigned int p_clock_; unsigned short h_; unsigned short hb_; unsigned short hspol_hsoff_; unsigned short hsw_; unsigned short v_; unsigned short vb_; unsigned short vspol_vsoff_; unsigned short vsw_; unsigned char vbs3d_; unsigned char modes_2d_s3d_; unsigned char p_depth_; H264Codec h264_codec_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_PREFERREDDISPLAYMODE_H_ ================================================ FILE: libwds/rtsp/presentationurl.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/presentationurl.h" namespace wds { namespace rtsp { PresentationUrl::PresentationUrl(const std::string& presentation_url_1, const std::string presentation_url_2) : Property(PresentationURLPropertyType), presentation_url_1_(presentation_url_1), presentation_url_2_(presentation_url_2) { } PresentationUrl::~PresentationUrl() { } std::string PresentationUrl::ToString() const { std::string ret = PropertyName::wfd_presentation_url + std::string(SEMICOLON) + std::string(SPACE) + (presentation_url_1_.length() ? presentation_url_1_ : NONE) + std::string(SPACE) + (presentation_url_2_.length() ? presentation_url_2_ : NONE); return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/presentationurl.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_PRESENTATIONURL_H_ #define LIBWDS_RTSP_PRESENTATIONURL_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class PresentationUrl: public Property { public: PresentationUrl(const std::string& presentation_url_1, const std::string presentation_url_2); ~PresentationUrl() override; const std::string& presentation_url_1() const { return presentation_url_1_; } const std::string& presentation_url_2() const { return presentation_url_2_; } std::string ToString() const override; private: std::string presentation_url_1_; std::string presentation_url_2_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_PRESENTATIONURL_H_ ================================================ FILE: libwds/rtsp/property.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/property.h" #include "libwds/public/logging.h" namespace wds { namespace rtsp { Property::Property(PropertyType type) : type_(type), is_none_(false) { } Property::Property(PropertyType type, bool is_none) : type_(type), is_none_(is_none) { } Property::~Property() { } std::string Property::ToString() const { return std::string(); } std::string Property::GetName() const { if (type_ == GenericPropertyType) return std::string(); return GetPropertyName(type_); } std::string GetPropertyName(PropertyType type) { switch(type) { case AVFormatChangeTimingPropertyType: return PropertyName::wfd_av_format_change_timing; case AudioCodecsPropertyType: return PropertyName::wfd_audio_codecs; case ClientRTPPortsPropertyType: return PropertyName::wfd_client_rtp_ports; case ConnectorTypePropertyType: return PropertyName::wfd_connector_type; case ContentProtectionPropertyType: return PropertyName::wfd_content_protection; case CoupledSinkPropertyType: return PropertyName::wfd_coupled_sink; case DisplayEdidPropertyType: return PropertyName::wfd_display_edid; case GenericPropertyType: WDS_ERROR("Generic property does not have a defined name"); return std::string(); case I2CPropertyType: return PropertyName::wfd_I2C; case IDRRequestPropertyType: return PropertyName::wfd_idr_request; case PreferredDisplayModePropertyType: return PropertyName::wfd_preferred_display_mode; case PresentationURLPropertyType: return PropertyName::wfd_presentation_url; case RoutePropertyType: return PropertyName::wfd_route; case StandbyPropertyType: return PropertyName::wfd_standby; case StandbyResumeCapabilityPropertyType: return PropertyName::wfd_standby_resume_capability; case TriggerMethodPropertyType: return PropertyName::wfd_trigger_method; case UIBCCapabilityPropertyType: return PropertyName::wfd_uibc_capability; case UIBCSettingPropertyType: return PropertyName::wfd_uibc_setting; case Video3DFormatsPropertyType: return PropertyName::wfd_3d_video_formats; case VideoFormatsPropertyType: return PropertyName::wfd_video_formats; default: WDS_ERROR("Unknown property type %d", type); return std::string(); } } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/property.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_PROPERTY_H_ #define LIBWDS_RTSP_PROPERTY_H_ #include #include #include "libwds/rtsp/constants.h" namespace wds { namespace rtsp { class Property { public: explicit Property(PropertyType type); virtual ~Property(); virtual std::string ToString() const; PropertyType type() { return type_; } bool is_none() const { return is_none_; } virtual std::string GetName() const; protected: Property(PropertyType type, bool is_none_); private: PropertyType type_; bool is_none_; }; std::string GetPropertyName(PropertyType type); } // namespace wds } // namespace rtsp #endif // LIBWDS_RTSP_PROPERTY_H_ ================================================ FILE: libwds/rtsp/propertyerrors.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/propertyerrors.h" #include "libwds/rtsp/property.h" #include namespace wds { namespace rtsp { PropertyErrors::PropertyErrors(PropertyType type, const std::vector& error_codes) : type_(type), error_codes_(error_codes) { } PropertyErrors::PropertyErrors(const std::string& generic_property_name, const std::vector& error_codes) : type_(GenericPropertyType), generic_property_name_(generic_property_name), error_codes_(error_codes) { } PropertyErrors::~PropertyErrors() { } std::string PropertyErrors::ToString() const { std::string ret; if (type_ == GenericPropertyType) ret += generic_property_name_; else ret += GetPropertyName(type_); ret += std::string(SEMICOLON) + std::string(SPACE); auto it = error_codes_.begin(); while (it != error_codes_.end()) { ret += std::to_string(*it); it++; if (it != error_codes_.end()) ret += ", "; } return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/propertyerrors.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_PROPERTYERRORS_H_ #define LIBWDS_RTSP_PROPERTYERRORS_H_ #include #include #include "libwds/rtsp/constants.h" namespace wds { namespace rtsp { class PropertyErrors { public: PropertyErrors(PropertyType type, const std::vector& error_codes); PropertyErrors(const std::string& generic_property_name, const std::vector& error_codes); ~PropertyErrors(); PropertyType type() const { return type_; } const std::vector& error_codes() const { return error_codes_; } const std::string& generic_property_name() const { return generic_property_name_; } std::string ToString() const; private: PropertyType type_; std::string generic_property_name_; std::vector error_codes_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_PROPERTYERRORS_H_ ================================================ FILE: libwds/rtsp/reply.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/reply.h" namespace wds { namespace rtsp { namespace { const char kRTSPHeader[] = "RTSP/1.0 "; const char kOK[] = "OK"; } Reply::Reply(int response_code) : Message(Message::REPLY), response_code_(response_code) { } Reply::~Reply() { } std::string Reply::ToString() const { std::string ret; ret += kRTSPHeader + std::to_string(response_code_) + std::string(SPACE) + kOK + std::string(CRLF); return ret + Message::ToString(); } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/reply.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_REPLY_H_ #define LIBWDS_RTSP_REPLY_H_ #include "libwds/rtsp/message.h" namespace wds { namespace rtsp { class Reply: public Message { public: explicit Reply(int response_code = STATUS_OK); ~Reply() override; int response_code() const { return response_code_; } void set_response_code(int response_code) { response_code_ = response_code; } std::string ToString() const override; private: int response_code_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_REPLY_H_ ================================================ FILE: libwds/rtsp/route.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/route.h" namespace wds { namespace rtsp { namespace { const char primary[] = "primary"; const char secondary[] = "secondary"; } Route::Route(const Route::Destination& destination) : Property(RoutePropertyType), destination_(destination) { } Route::~Route() { } std::string Route::ToString() const { std::string ret = PropertyName::wfd_route+ std::string(SEMICOLON) + std::string(SPACE) + (destination() == PRIMARY ? primary : secondary); return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/route.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_ROUTE_H_ #define LIBWDS_RTSP_ROUTE_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class Route: public Property { public: enum Destination { PRIMARY, SECONDARY }; public: explicit Route(const Route::Destination& destination); ~Route() override; Route::Destination destination() const { return destination_; } std::string ToString() const override; private: Route::Destination destination_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_ROUTE_H_ ================================================ FILE: libwds/rtsp/setparameter.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/setparameter.h" #include "libwds/rtsp/triggermethod.h" namespace wds { namespace rtsp { SetParameter::SetParameter(const std::string& request_uri) : Request(Request::MethodSetParameter, request_uri) { } std::string SetParameter::ToString() const { std::string ret = MethodName::SET_PARAMETER + std::string(SPACE) + request_uri() + std::string(SPACE) + std::string(RTSP_END) + std::string(CRLF); return ret + Message::ToString(); } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/setparameter.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_SETPARAMETER_H_ #define LIBWDS_RTSP_SETPARAMETER_H_ #include "libwds/rtsp/message.h" namespace wds { namespace rtsp { class SetParameter : public Request { public: explicit SetParameter(const std::string& request_uri); std::string ToString() const override; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_SETPARAMETER_H_ ================================================ FILE: libwds/rtsp/setup.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/setup.h" namespace wds { namespace rtsp { Setup::Setup(const std::string& request_uri) : Request(Request::MethodSetup, request_uri) { } Setup::~Setup() { } std::string Setup::ToString() const { std::string ret = MethodName::SETUP + std::string(SPACE) + request_uri() + std::string(SPACE) + std::string(RTSP_END) + std::string(CRLF); return ret + Message::ToString(); } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/setup.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_SETUP_H_ #define LIBWDS_RTSP_SETUP_H_ #include "libwds/rtsp/message.h" namespace wds { namespace rtsp { class Setup : public Request { public: explicit Setup(const std::string& request_uri); ~Setup() override; std::string ToString() const override; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_SETUP_H_ ================================================ FILE: libwds/rtsp/standby.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/standby.h" namespace wds { namespace rtsp { Standby::Standby() : Property(StandbyPropertyType) { } Standby::~Standby() { } std::string Standby::ToString() const { return std::string("wfd_standby"); } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/standby.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_STANDBY_H_ #define LIBWDS_RTSP_STANDBY_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class Standby: public Property { public: Standby(); ~Standby() override; std::string ToString() const override; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_STANDBY_H_ ================================================ FILE: libwds/rtsp/standbyresumecapability.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/standbyresumecapability.h" namespace wds { namespace rtsp { namespace { const char supported[] = "supported"; } StandbyResumeCapability::StandbyResumeCapability(bool is_supported) : Property(StandbyResumeCapabilityPropertyType, !is_supported) { } StandbyResumeCapability::~StandbyResumeCapability() { } std::string StandbyResumeCapability::ToString() const { std::string ret = PropertyName::wfd_standby_resume_capability + std::string(SEMICOLON) + std::string(SPACE) + (is_none() ? NONE : supported); return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/standbyresumecapability.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_STANDBYRESUMECAPABILITY_H_ #define LIBWDS_RTSP_STANDBYRESUMECAPABILITY_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class StandbyResumeCapability: public Property { public: explicit StandbyResumeCapability(bool is_supported); ~StandbyResumeCapability() override; std::string ToString() const override; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_STANDBYRESUMECAPABILITY_H_ ================================================ FILE: libwds/rtsp/teardown.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/teardown.h" namespace wds { namespace rtsp { Teardown::Teardown(const std::string& request_uri) : Request(Request::MethodTeardown, request_uri) { } Teardown::~Teardown() { } std::string Teardown::ToString() const { std::string ret = MethodName::TEARDOWN + std::string(SPACE) + request_uri() + std::string(SPACE) + std::string(RTSP_END) + std::string(CRLF); return ret + Message::ToString(); } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/teardown.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_TEARDOWN_H_ #define LIBWDS_RTSP_TEARDOWN_H_ #include "libwds/rtsp/message.h" namespace wds { namespace rtsp { class Teardown : public Request { public: explicit Teardown(const std::string& request_uri); ~Teardown() override; std::string ToString() const override; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_TEARDOWN_H_ ================================================ FILE: libwds/rtsp/tests/CMakeLists.txt ================================================ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fvisibility=hidden -fPIC") set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -std=c99 -Wall") include_directories ("${PROJECT_SOURCE_DIR}" "../gen") add_executable(test-wds tests.cpp $ $) set(LINK_FLAGS ${LINK_FLAGS} "-Wl,-whole-archive") target_link_libraries (test-wds) add_test(WfdTest test-wds) if (WDS_INSTALL_TESTS) install(PROGRAMS test-wds DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}) endif() OPTION(WDS_FUZZER "Binary that is used for fuzzer tests." OFF) IF(WDS_FUZZER) add_executable(wdsfuzzer wdsfuzzer.cpp $ $) set(LINK_FLAGS ${LINK_FLAGS} "-Wl,-whole-archive") target_link_libraries (wdsfuzzer) ENDIF(WDS_FUZZER) ================================================ FILE: libwds/rtsp/tests/README ================================================ ======================= How to fuzz WDS parser ======================= 1) Get afl-fuzz from http://lcamtuf.coredump.cx/afl/ and follow "QuickStartGuide" http://lcamtuf.coredump.cx/afl/QuickStartGuide.txt 2) Build WDS with WDS_FUZZER support. Provide full path to afl-gcc / afl-g++ or add path containing afl-* binaries to your PATH environment variable. CC=afl-gcc CXX=afl-g++ cmake -DWDS_FUZZER=ON --disable-shared . 3) Run run_afl_fuzzer.sh script which is located under libwds/rtsp/tests folder ./libwds/rtsp/tests/run_afl_fuzzer.sh PATH_TO_AFL_FUZZ TEST_RESULT_PATH e.g. ./libwds/rtsp/tests/run_afl_fuzzer.sh afl-fuzz test_results Four fuzzer jobs will be started (header, payload_request, payload_reply and payload_error), each testing independent lexing / parsing code paths. 4) Observe progress in separate xterm terminal or use afl-whatsup to get status of fuzzing job with afl-whatsup. 5) For more information check http://lcamtuf.coredump.cx/afl/README.txt or docs folder under afl-fuzz source tree. ================================================ FILE: libwds/rtsp/tests/dict/wfd_header.dict ================================================ # This file is part of Wireless Display Software for Linux OS # # Copyright (C) 2016 Intel Corporation. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA # WiFi Display RTSP dictionary for request / response headers method_OPTIONS="OPTIONS" method_WFD="org.wfa.wfd1.0" method_SET_PARAMETER="SET_PARAMETER" method_GET_PARAMETER="GET_PARAMETER" method_SETUP="SETUP" method_PLAY="PLAY" method_TEARDOWN="TEARDOWN" method_PAUSE="PAUSE" header_RESPONSE="RTSP/1.0" header_CSeq="CSeq:" header_SupportedMethods="Public:" header_Require="Require:" header_ContentType="Content-Type:" header_ContentLength="Content-Length:" header_Session="Session:" header_Transport="Transport:" header_star="*" header_status"OK" header_date="Date:" token_Timeout="timeout=" token_ServerPort="server_port=" token_ServerPort="client_port=" token_RTPUDP="RTP/AVP/UDP" token_unicast="unicast" data_url="rtsp://localhost/wfd1.0" data_url_ip="rtsp://192.168.0.101/wfd1.0" data_error_code="200" ================================================ FILE: libwds/rtsp/tests/dict/wfd_payload_error.dict ================================================ # This file is part of Wireless Display Software for Linux OS # # Copyright (C) 2016 Intel Corporation. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA # WiFi Display RTSP dictionary for payload with response error payload_wfd_audio_codecs="wfd-audio-codecs:" payload_wfd_video_formats="wfd-video-formats:" payload_wfd_3d_formats="wfd-3d-formats:" payload_wfd_content_protection="wfd-content-protection:" payload_wfd_display_edid="wfd-display-edid:" payload_wfd_coupled_sink="wfd-coupled-sink:" payload_wfd_trigger_method="wfd-trigger-method:" payload_wfd_presentation_url="wfd-presentation-url:" payload_wfd_client_rtp_ports="wfd-client-rtp-ports:" payload_wfd_route="wfd-route:" payload_wfd_I2C="wfd-I2C:" payload_wfd_av_format_change_timing="wfd-av-format-change-timing:" payload_wfd_preferred_display_mode="wfd-preferred-display-mode:" payload_wfd_uibc_capability="wfd-uibc-capability:" payload_wfd_uibc_setting="wfd-uibc-setting:" payload_wfd_standby_resume_capability="wfd-standby-resume-capability:" payload_wfd_standby="wfd-standby:" payload_wfd_connector_type="wfd-connector-type:" payload_wfd_idr_request="wfd-idr-request:" token_SEPARATOR=", " ================================================ FILE: libwds/rtsp/tests/dict/wfd_payload_reply.dict ================================================ # This file is part of Wireless Display Software for Linux OS # # Copyright (C) 2016 Intel Corporation. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA # WiFi Display RTSP dictionary payload response payload_wfd_audio_codecs="wfd-audio-codecs:" payload_wfd_video_formats="wfd-video-formats:" payload_wfd_3d_formats="wfd-3d-formats:" payload_wfd_content_protection="wfd-content-protection:" payload_wfd_display_edid="wfd-display-edid:" payload_wfd_coupled_sink="wfd-coupled-sink:" payload_wfd_trigger_method="wfd-trigger-method:" payload_wfd_presentation_url="wfd-presentation-url:" payload_wfd_client_rtp_ports="wfd-client-rtp-ports:" payload_wfd_route="wfd-route:" payload_wfd_I2C="wfd-I2C:" payload_wfd_av_format_change_timing="wfd-av-format-change-timing:" payload_wfd_preferred_display_mode="wfd-preferred-display-mode:" payload_wfd_uibc_capability="wfd-uibc-capability:" payload_wfd_uibc_setting="wfd-uibc-setting:" payload_wfd_standby_resume_capability="wfd-standby-resume-capability:" payload_wfd_standby="wfd-standby:" payload_wfd_connector_type="wfd-connector-type:" payload_wfd_idr_request="wfd-idr-request:" token_none="none" token_LPCM="LPCM" token_AAC="AAC" token_AC3="AC3" token_HDCP20="HDCP2.0" token_HDCP21="HDCP2.1" token_port="port=" token_RTP="RTP/AVP/UDP;unicast" token_mode_play="mode=play" token_primary="primary" token_secondary="secondary" token_input_category_list=="input_category_list=" token_GENERIC="GENERIC" token_HIDC="HIDC" token_generic_cap_list=="generic_cap_list=" token_Keyboard="Keyboard" token_Mouse="Mouse" token_SingleTouch="SingleTouch" token_MultiTouch="MultiTouch" token_Joystick="Joystick" token_Camera="Camera" token_Gesture="Gesture" token_RemoteControl="RemoteControl" token_hidc_cap_list=="hidc_cap_list=" token_Infrared="Infrared" token_USB="USB" token_BT="BT" token_WiFi="Wi-Fi" token_Zigbee="Zigbee" token_NoSP="No-SP" token_disable="disable" token_enable="enable" token_supported="supported" ================================================ FILE: libwds/rtsp/tests/dict/wfd_payload_request.dict ================================================ # This file is part of Wireless Display Software for Linux OS # # Copyright (C) 2016 Intel Corporation. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA # WiFi Display RTSP dictionary for GET_PARAMETER request messages payload_wfd_audio_codecs="wfd-audio-codecs" payload_wfd_video_formats="wfd-video-formats" payload_wfd_3d_formats="wfd-3d-formats" payload_wfd_content_protection="wfd-content-protection" payload_wfd_display_edid="wfd-display-edid" payload_wfd_coupled_sink="wfd-coupled-sink" payload_wfd_trigger_method="wfd-trigger-method" payload_wfd_presentation_url="wfd-presentation-url" payload_wfd_client_rtp_ports="wfd-client-rtp-ports" payload_wfd_route="wfd-route" payload_wfd_I2C="wfd-I2C" payload_wfd_av_format_change_timing="wfd-av-format-change-timing" payload_wfd_preferred_display_mode="wfd-preferred-display-mode" payload_wfd_uibc_capability="wfd-uibc-capability" payload_wfd_uibc_setting="wfd-uibc-setting" payload_wfd_standby_resume_capability="wfd-standby-resume-capability" payload_wfd_standby="wfd-standby" payload_wfd_connector_type="wfd-connector-type" payload_wfd_idr_request="wfd-idr-request" token_newline="0x0d0x0a" ================================================ FILE: libwds/rtsp/tests/run_afl_fuzzer.sh ================================================ #!/bin/bash # This file is part of Wireless Display Software for Linux OS # # Copyright (C) 2016 Intel Corporation. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA BASEDIR=$(dirname $0) xterm -geometry 80x25 -e "$1 -i $BASEDIR/seed/header/ -x $BASEDIR/dict/wfd_header.dict -o $2_header -T header $BASEDIR/wdsfuzzer --num-lines 6 --header" & xterm -geometry 80x25 -e "$1 -i $BASEDIR/seed/payload_reply/ -x $BASEDIR/dict/wfd_payload_reply.dict -o $2_payload_reply -T payload_reply $BASEDIR/wdsfuzzer --num-lines 8 --payload-reply" & xterm -geometry 80x25 -e "$1 -i $BASEDIR/seed/payload_request/ -x $BASEDIR/dict/wfd_payload_request.dict -o $2_payload_request -T payload_request $BASEDIR/wdsfuzzer --num-lines 8 --payload-request" & xterm -geometry 80x25 -e "$1 -i $BASEDIR/seed/payload_error/ -x $BASEDIR/dict/wfd_payload_error.dict -o $2_payload_error -T payload_error $BASEDIR/wdsfuzzer --num-lines 8 --payload-error" & ================================================ FILE: libwds/rtsp/tests/seed/header/error.txt ================================================ RTSP/1.0 303 OK CSeq: 0 Content-Type: text/parameters Content-Length: 55 ================================================ FILE: libwds/rtsp/tests/seed/header/get_parameter.txt ================================================ GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: 2 Content-Type: text/parameters Content-Length: 141 ================================================ FILE: libwds/rtsp/tests/seed/header/options.txt ================================================ OPTIONS * RTSP/1.0 CSeq: 1 Require: org.wfa.wfd1.0 ================================================ FILE: libwds/rtsp/tests/seed/header/pause.txt ================================================ PAUSE rtsp://10.82.24.140/wfd1.0/streamid=0 RTSP/1.0 CSeq: 6 Session: 6B8B4567 ================================================ FILE: libwds/rtsp/tests/seed/header/play.txt ================================================ PLAY rtsp://10.82.24.140/wfd1.0/streamid=0 RTSP/1.0 CSeq: 5 Session: 6B8B4567 ================================================ FILE: libwds/rtsp/tests/seed/header/reply.txt ================================================ RTSP/1.0 200 OK CSeq: 4 Date: Sun, Aug 21 2011 04:20:53 GMT Public: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER ================================================ FILE: libwds/rtsp/tests/seed/header/set_parameter.txt ================================================ SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0 CSeq: 3 Content-Type: text/parameters Content-Length: 302 ================================================ FILE: libwds/rtsp/tests/seed/header/setup.txt ================================================ SETUP rtsp://10.82.24.140/wfd1.0/streamid=0 RTSP/1.0 CSeq: 4 Transport: RTP/AVP/UDP;unicast;client_port=1028 ================================================ FILE: libwds/rtsp/tests/seed/header/teardown.txt ================================================ TEARDOWN rtsp://10.82.24.140/wfd1.0/streamid=0 RTSP/1.0 CSeq: 8 Session: 6B8B4567 ================================================ FILE: libwds/rtsp/tests/seed/payload_error/payload_error01.txt ================================================ wfd_3d_video_formats: 415, 457 wfd_I2C: 404 wfd_audio_codecs: 415, 457 wfd_client_rtp_ports: 415, 457 wfd_connector_type: 415, 457 wfd_content_protection: 404 wfd_coupled_sink: 404 wfd_display_edid: 503 wfd_standby_resume_capability: 415, 457 wfd_uibc_capability: 494 wfd_video_formats: 415, 457 ================================================ FILE: libwds/rtsp/tests/seed/payload_error/payload_error02.txt ================================================ wfd-audio-codecs: 415, 457 wfd-video-formats: 415, 457 wfd-3d-formats: 415, 457 wfd-content-protection: 404 wfd-display-edid: 415, 457 wfd-coupled-sink: 465 wfd-trigger-method: 457 wfd-presentation-url: 401 wfd-client-rtp-ports: 401 wfd-route: 404 wfd-I2C: 404 wfd-av-format-change-timing: 451 wfd-preferred-display-mode: 401 wfd-uibc-capability: 404 wfd-uibc-setting: 401 wfd-standby-resume-capability: 415 wfd-standby: 465 wfd-connector-type: 503 wfd-idr-request: 303 ================================================ FILE: libwds/rtsp/tests/seed/payload_reply/payload_reply01.txt ================================================ wfd_I2C: 404 wfd_audio_codecs: LPCM 00000003 00, AAC 00000001 00 wfd_client_rtp_ports: RTP/AVP/UDP;unicast 19000 0 mode=play wfd_connector_type: 05 wfd_content_protection: HDCP2.1 port=1189 wfd_coupled_sink: none wfd_display_edid: none wfd_standby_resume_capability: supported wfd_uibc_capability: none wfd_video_formats: 40 01 02 04 0001DEFF 053C7FFF 00000FFF 00 0000 0000 11 0400 0300, 01 04 0001DEFF 053C7FFF 00000FFF 00 0000 0000 11 0400 0300 wfd_3d_video_formats: 80 00 03 0F 0000000000000005 00 0001 1401 13 none none ================================================ FILE: libwds/rtsp/tests/seed/payload_reply/payload_reply02.txt ================================================ wfd_audio_codecs: LPCM 00000003 00 wfd_3d_video_formats: none wfd_content_protection: none wfd_display_edid: none wfd_coupled_sink: none wfd_client_rtp_ports: RTP/AVP/UDP;unicast 1028 0 mode=play wfd_presentation_URL: rtsp://192.168.173.1:3921/wfd1.0/streamid=0 rtsp://192.168.173.1:3922/wfd1.0/streamid=1 wfd_trigger_method: TEARDOWN ================================================ FILE: libwds/rtsp/tests/seed/payload_request/payload_request01.txt ================================================ wfd_video_formats wfd_audio_codecs wfd_client_rtp_ports ================================================ FILE: libwds/rtsp/tests/seed/payload_request/payload_request02.txt ================================================ wfd-audio-codecs wfd-video-formats wfd-3d-formats wfd-content-protection wfd-display-edid wfd-coupled-sink wfd-trigger-method wfd-presentation-url wfd-client-rtp-ports wfd-route wfd-I2C wfd-av-format-change-timing wfd-preferred-display-mode wfd-uibc-capability wfd-uibc-setting wfd-standby-resume-capability wfd-standby wfd-connector-type wfd-idr-request ================================================ FILE: libwds/rtsp/tests/tests.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include "libwds/rtsp/audiocodecs.h" #include "libwds/rtsp/avformatchangetiming.h" #include "libwds/rtsp/clientrtpports.h" #include "libwds/rtsp/connectortype.h" #include "libwds/rtsp/constants.h" #include "libwds/rtsp/contentprotection.h" #include "libwds/rtsp/displayedid.h" #include "libwds/rtsp/driver.h" #include "libwds/rtsp/formats3d.h" #include "libwds/rtsp/i2c.h" #include "libwds/rtsp/presentationurl.h" #include "libwds/rtsp/propertyerrors.h" #include "libwds/rtsp/reply.h" #include "libwds/rtsp/route.h" #include "libwds/rtsp/triggermethod.h" #include "libwds/rtsp/uibcsetting.h" #include "libwds/rtsp/videoformats.h" using wds::rtsp::Driver; typedef bool (*TestFunc)(void); #define ASSERT_EQUAL(value, expected) \ if ((value) != (expected)) { \ std::cout << __func__ << " (" << __FILE__ << ":" << __LINE__ << "): " \ << #value << ": " \ << "expected '" << (expected) \ << "', got '" << (value) << "'" \ << std::endl; \ return 0; \ } #define ASSERT(assertion) \ if (!(assertion)) { \ std::cout << __func__ << " (" << __FILE__ << ":" << __LINE__ << "): " \ << "assertion failed: " << #assertion \ << std::endl; \ return 0; \ } #define ASSERT_NO_EXCEPTION(method_call) \ try { \ method_call; \ } catch (std::exception &x) { \ std::cout << __func__ << " (" << __FILE__ << ":" << __LINE__ << "): " \ << "unexpected exception: " << #method_call << ": " \ << x.what() << std::endl; \ return false; \ } #define ASSERT_EXCEPTION(method_call) \ try { \ method_call; \ std::cout << __func__ << " (" << __FILE__ << ":" << __LINE__ << "): " \ << "expected exception: " << #method_call << std::endl; \ return false; \ } catch (std::exception &x) { \ ; \ } static bool property_type_exists (std::vector properties, wds::rtsp::PropertyType type) { return std::find (properties.begin(), properties.end(), wds::rtsp::GetPropertyName(type)) != properties.end(); } static bool test_audio_codec (wds::AudioCodec codec, wds::AudioFormats format, unsigned long int modes, unsigned char latency) { ASSERT_EQUAL(codec.format, format); ASSERT_EQUAL(codec.modes.to_ulong(), modes); ASSERT_EQUAL(codec.latency, latency); return true; } static bool test_h264_codec_3d (wds::rtsp::H264Codec3d codec, unsigned char profile, unsigned char level, unsigned long long int video_capability_3d, unsigned char latency, unsigned short min_slice_size, unsigned short slice_enc_params, unsigned char frame_rate_control_support, int max_hres, int max_vres) { ASSERT_EQUAL(codec.profile_, profile); ASSERT_EQUAL(codec.level_, level); ASSERT_EQUAL(codec.video_capability_3d_, video_capability_3d); ASSERT_EQUAL(codec.latency_, latency); ASSERT_EQUAL(codec.min_slice_size_, min_slice_size); ASSERT_EQUAL(codec.slice_enc_params_, slice_enc_params); ASSERT_EQUAL(codec.frame_rate_control_support_, frame_rate_control_support); return true; } static bool test_valid_options () { std::string header("OPTIONS * RTSP/1.0\r\n" "CSeq: 0\r\n" "Require: org.wfa.wfd1.0\r\n\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_request()); wds::rtsp::Request* request = wds::rtsp::ToRequest(message.get()); ASSERT_EQUAL(request->method(), wds::rtsp::Request::MethodOptions); ASSERT_EQUAL(request->header().cseq(), 0); ASSERT_EQUAL(request->header().content_length(), 0); ASSERT_EQUAL(request->header().require_wfd_support(), true); ASSERT_EQUAL (request->ToString(), header); return true; } static bool test_valid_options_reply () { std::string header("RTSP/1.0 200 OK\r\n" "CSeq: 1\r\n" "Public: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER\r\n\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); wds::rtsp::Reply* reply = static_cast(message.get()); ASSERT(reply != NULL); ASSERT_EQUAL(reply->response_code(), 200); ASSERT_EQUAL(reply->header().cseq(), 1); ASSERT_EQUAL(reply->header().content_length(), 0); std::vector methods = message->header().supported_methods(); static const wds::rtsp::Method expected[] = { wds::rtsp::Method::ORG_WFA_WFD_1_0, wds::rtsp::Method::SETUP, wds::rtsp::Method::TEARDOWN, wds::rtsp::Method::PLAY, wds::rtsp::Method::PAUSE, wds::rtsp::Method::GET_PARAMETER, wds::rtsp::Method::SET_PARAMETER }; ASSERT_EQUAL(methods.size(), 7); for (int i = 0; i < 7; i++) { std::vector::iterator method = std::find(methods.begin(), methods.end(), expected[i]); ASSERT(method != methods.end()); } ASSERT_EQUAL (reply->ToString(), header); return true; } static bool test_valid_extra_properties () { std::string header("RTSP/1.0 200 OK\r\n" "CSeq: 2\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 72\r\n" "My-Header: 123 testing testing\r\n\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); GenericHeaderMap gen_headers = message->header().generic_headers(); auto extra_header_it = gen_headers.find("My-Header"); ASSERT(extra_header_it != gen_headers.end()) ASSERT_EQUAL(extra_header_it->second, "123 testing testing"); ASSERT_EQUAL(message->header().content_length(), 72); std::string payload_buffer("nonstandard_property: 1!!1! non standard value\r\n" "wfd_audio_codecs: none\r\n"); Driver::Parse(payload_buffer, message); auto payload = ToPropertyMapPayload(message->payload()); ASSERT(payload); std::shared_ptr property; ASSERT_NO_EXCEPTION (property = payload->GetProperty(wds::rtsp::AudioCodecsPropertyType)); ASSERT(property->is_none()); ASSERT_NO_EXCEPTION (property = payload->GetProperty("nonstandard_property")); auto extra_property = std::static_pointer_cast(property); ASSERT_EQUAL(extra_property->value(), "1!!1! non standard value"); ASSERT_EQUAL(message->ToString(), header + payload_buffer); return true; } static bool test_valid_extra_errors () { std::string header("RTSP/1.0 303 OK\r\n" "CSeq: 0\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 55\r\n\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); std::string payload_buffer("wfd_audio_codecs: 103\r\n" "nonstandard_property: 101, 102\r\n"); Driver::Parse(payload_buffer, message); ASSERT(message != NULL); auto payload = ToPropertyErrorPayload(message->payload()); ASSERT(payload); std::shared_ptr error; ASSERT_EQUAL(payload->property_errors().size(), 2); ASSERT_NO_EXCEPTION(error = payload->GetPropertyError(wds::rtsp::AudioCodecsPropertyType)); ASSERT_EQUAL(error->error_codes().size(), 1); ASSERT_EQUAL(error->error_codes()[0], 103); ASSERT_NO_EXCEPTION(error = payload->GetPropertyError("nonstandard_property")); ASSERT_EQUAL(error->error_codes().size(), 2); ASSERT_EQUAL(error->error_codes()[0], 101); ASSERT_EQUAL(error->error_codes()[1], 102); ASSERT_EQUAL(message->ToString(), header + payload_buffer); return true; } static bool test_valid_extra_properties_in_get () { std::string header("GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n" "CSeq: 2\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 40\r\n\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_request()); wds::rtsp::Request* request = wds::rtsp::ToRequest(message.get()); ASSERT_EQUAL(request->method(), wds::rtsp::Request::MethodGetParameter); std::string payload_buffer("nonstandard_property\r\n" "wfd_audio_codecs\r\n"); Driver::Parse(payload_buffer, message); auto payload = ToGetParameterPayload(message->payload()); ASSERT(payload); auto properties = payload->properties(); ASSERT(property_type_exists (properties, wds::rtsp::AudioCodecsPropertyType)); ASSERT_EQUAL(properties.size(), 2); ASSERT_EQUAL(properties[0], "nonstandard_property"); ASSERT_EQUAL(properties[1], "wfd_audio_codecs"); ASSERT_EQUAL(message->ToString(), header + payload_buffer); return true; } static bool test_valid_get_parameter () { std::string header("GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n" "CSeq: 2\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 213\r\n\r\n"); std::string payload_buffer("wfd_client_rtp_ports\r\n" "wfd_audio_codecs\r\n" "wfd_video_formats\r\n" "wfd_3d_video_formats\r\n" "wfd_coupled_sink\r\n" "wfd_display_edid\r\n" "wfd_connector_type\r\n" "wfd_uibc_capability\r\n" "wfd_standby_resume_capability\r\n" "wfd_content_protection\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_request()); Driver::Parse(payload_buffer, message); ASSERT(message != NULL); wds::rtsp::Request* request = wds::rtsp::ToRequest(message.get()); ASSERT_EQUAL(request->method(), wds::rtsp::Request::MethodGetParameter); ASSERT_EQUAL(request->request_uri(), "rtsp://localhost/wfd1.0"); ASSERT_EQUAL(message->header().cseq(), 2); ASSERT_EQUAL(message->header().content_length(), 213); ASSERT_EQUAL(message->header().content_type(), "text/parameters"); ASSERT_EQUAL(message->header().require_wfd_support(), false); auto payload = ToGetParameterPayload(message->payload()); ASSERT(payload); std::vector properties = payload->properties(); ASSERT(property_type_exists (properties, wds::rtsp::ClientRTPPortsPropertyType)); ASSERT(property_type_exists (properties, wds::rtsp::ClientRTPPortsPropertyType)); ASSERT(property_type_exists (properties, wds::rtsp::AudioCodecsPropertyType)); ASSERT(property_type_exists (properties, wds::rtsp::VideoFormatsPropertyType)); ASSERT(property_type_exists (properties, wds::rtsp::Video3DFormatsPropertyType)); ASSERT(property_type_exists (properties, wds::rtsp::CoupledSinkPropertyType)); ASSERT(property_type_exists (properties, wds::rtsp::DisplayEdidPropertyType)); ASSERT(property_type_exists (properties, wds::rtsp::ConnectorTypePropertyType)); ASSERT(property_type_exists (properties, wds::rtsp::UIBCCapabilityPropertyType)); ASSERT(property_type_exists (properties, wds::rtsp::StandbyResumeCapabilityPropertyType)); ASSERT(property_type_exists (properties, wds::rtsp::ContentProtectionPropertyType)); ASSERT_EQUAL (message->ToString(), header + payload_buffer) return true; } static bool test_valid_get_parameter_reply_with_all_none () { std::string header("RTSP/1.0 200 OK\r\n" "CSeq: 2\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 483\r\n\r\n"); // not a real-world message, just a collection of all properties std::string payload_buffer("wfd_3d_video_formats: none\r\n" "wfd_I2C: none\r\n" "wfd_audio_codecs: none\r\n" "wfd_av_format_change_timing: 000000000F 00000000FF\r\n" "wfd_client_rtp_ports: RTP/AVP/UDP;unicast 19000 0 mode=play\r\n" "wfd_connector_type: none\r\n" "wfd_content_protection: none\r\n" "wfd_coupled_sink: none\r\n" "wfd_display_edid: none\r\n" "wfd_presentation_URL: none none\r\n" "wfd_route: primary\r\n" "wfd_standby_resume_capability: none\r\n" "wfd_trigger_method: TEARDOWN\r\n" "wfd_uibc_capability: none\r\n" "wfd_uibc_setting: disable\r\n" "wfd_video_formats: none\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); Driver::Parse(payload_buffer, message); ASSERT(message != NULL); wds::rtsp::Reply* reply = static_cast(message.get()); ASSERT(reply != NULL); ASSERT_EQUAL(reply->response_code(), 200); ASSERT_EQUAL(reply->header().cseq(), 2); ASSERT_EQUAL(reply->header().content_length(), 483); ASSERT_EQUAL(reply->header().content_type(), "text/parameters"); ASSERT_EQUAL(reply->header().supported_methods().size(), 0); auto payload = ToPropertyMapPayload(message->payload()); ASSERT(payload); std::shared_ptr prop; ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::AudioCodecsPropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::VideoFormatsPropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::Video3DFormatsPropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::ContentProtectionPropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::DisplayEdidPropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::CoupledSinkPropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::UIBCCapabilityPropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::ConnectorTypePropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::StandbyResumeCapabilityPropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::AVFormatChangeTimingPropertyType)); auto av_format_change_timing = std::static_pointer_cast (prop); ASSERT_EQUAL(av_format_change_timing->pts(), 0x000000000F); ASSERT_EQUAL(av_format_change_timing->dts(), 0x00000000FF); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::ClientRTPPortsPropertyType)); auto client_rtp_ports = std::static_pointer_cast (prop); ASSERT_EQUAL(client_rtp_ports->rtp_port_0(), 19000); ASSERT_EQUAL(client_rtp_ports->rtp_port_1(), 0); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::TriggerMethodPropertyType)); auto trigger_method = std::static_pointer_cast (prop); ASSERT_EQUAL(trigger_method->method(), wds::rtsp::TriggerMethod::TEARDOWN); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::PresentationURLPropertyType)); auto presentation_url = std::static_pointer_cast (prop); ASSERT_EQUAL(presentation_url->presentation_url_1(), ""); ASSERT_EQUAL(presentation_url->presentation_url_2(), ""); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::RoutePropertyType)); auto route = std::static_pointer_cast (prop); ASSERT_EQUAL(route->destination(), wds::rtsp::Route::PRIMARY); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::I2CPropertyType)); auto i2c = std::static_pointer_cast (prop); ASSERT_EQUAL(i2c->is_supported(), false); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::UIBCSettingPropertyType)); auto uibc_setting = std::static_pointer_cast (prop); ASSERT_EQUAL(uibc_setting->is_enabled(), false); ASSERT_EQUAL(message->ToString(), header + payload_buffer); return true; } static bool test_valid_get_parameter_reply () { std::string header("RTSP/1.0 200 OK\r\n" "CSeq: 2\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 535\r\n\r\n"); std::string payload_buffer("wfd_3d_video_formats: 80 00 03 0F 0000000000000005 00 0001 1401 13 none none\r\n" "wfd_I2C: 404\r\n" "wfd_audio_codecs: LPCM 00000003 00, AAC 00000001 00\r\n" "wfd_client_rtp_ports: RTP/AVP/UDP;unicast 19000 0 mode=play\r\n" "wfd_connector_type: 05\r\n" "wfd_content_protection: HDCP2.1 port=1189\r\n" "wfd_coupled_sink: none\r\n" "wfd_display_edid: none\r\n" "wfd_standby_resume_capability: supported\r\n" "wfd_uibc_capability: none\r\n" "wfd_video_formats: 40 01 02 04 0001DEFF 053C7FFF 00000FFF 00 0000 0000 11 0400 0300, 01 04 0001DEFF 053C7FFF 00000FFF 00 0000 0000 11 0400 0300\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); Driver::Parse(payload_buffer, message); ASSERT(message != NULL); wds::rtsp::Reply* reply = static_cast(message.get()); ASSERT(reply != NULL); ASSERT_EQUAL(reply->response_code(), 200); ASSERT_EQUAL(reply->header().cseq(), 2); ASSERT_EQUAL(reply->header().content_length(), 535); ASSERT_EQUAL(reply->header().content_type(), "text/parameters"); ASSERT_EQUAL(reply->header().supported_methods().size(), 0); auto payload = ToPropertyMapPayload(message->payload()); ASSERT(payload); std::shared_ptr prop; ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::AudioCodecsPropertyType)); // Test that all properties exist ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::AudioCodecsPropertyType)); std::shared_ptr audio_codecs = std::static_pointer_cast (prop); ASSERT_EQUAL(audio_codecs->audio_codecs().size(), 2); ASSERT(test_audio_codec (audio_codecs->audio_codecs()[0], wds::LPCM, 3, 0)); ASSERT(test_audio_codec (audio_codecs->audio_codecs()[1], wds::AAC, 1, 0)); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::VideoFormatsPropertyType)); std::shared_ptr video_formats = std::static_pointer_cast (prop); ASSERT_EQUAL(video_formats->GetNativeFormat().rate_resolution, 8); ASSERT_EQUAL(video_formats->GetNativeFormat().type, 0); ASSERT_EQUAL(video_formats->GetH264Formats().size(), 96); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::Video3DFormatsPropertyType)); std::shared_ptr formats_3d = std::static_pointer_cast (prop); ASSERT_EQUAL(formats_3d->native_resolution(), 0x80); ASSERT_EQUAL(formats_3d->preferred_display_mode(), 0); ASSERT_EQUAL(formats_3d->codecs().size(), 1); ASSERT(test_h264_codec_3d (formats_3d->codecs()[0], 0x03, 0x0F, 0x0000000000000005, 0, 0x0001, 0x1401, 0x13, 0, 0)); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::ContentProtectionPropertyType)); std::shared_ptr content_protection = std::static_pointer_cast (prop); ASSERT_EQUAL(content_protection->hdcp_spec(), wds::rtsp::ContentProtection::HDCP_SPEC_2_1); ASSERT_EQUAL(content_protection->port(), 1189); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::DisplayEdidPropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::CoupledSinkPropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::ClientRTPPortsPropertyType)); std::shared_ptr client_rtp_ports = std::static_pointer_cast (prop); ASSERT_EQUAL(client_rtp_ports->rtp_port_0(), 19000); ASSERT_EQUAL(client_rtp_ports->rtp_port_1(), 0); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::UIBCCapabilityPropertyType)); ASSERT(prop->is_none()); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::ConnectorTypePropertyType)); std::shared_ptr connector_type = std::static_pointer_cast (prop); ASSERT_EQUAL(connector_type->connector_type(), 5); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::I2CPropertyType)); auto i2c = std::static_pointer_cast (prop); ASSERT_EQUAL(i2c->is_supported(), true); ASSERT_EQUAL(i2c->port(), 404); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::StandbyResumeCapabilityPropertyType)); ASSERT(!prop->is_none()); ASSERT_EQUAL(message->ToString(), header + payload_buffer); return true; } static bool test_invalid_property_value () { std::string header("RTSP/1.0 200 OK\r\n" "CSeq: 2\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 1187\r\n"); std::string payload_buffer("wfd_uibc_capability: none and something completely different\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); Driver::Parse(payload_buffer, message); ASSERT(message == NULL); return true; } static bool test_case_insensitivity () { std::string invalid_header("OptionS * RTSP/1.0\r\n" "CSeq: 0\r\n" "Require: org.wfa.wfd1.0\r\n\r\n"); std::unique_ptr message; Driver::Parse(invalid_header, message); ASSERT(message == NULL); std::string header("RTSP/1.0 200 OK\r\n" "CSEQ: 2\r\n" "Content-Type: tEXT/parameters\r\n" "Content-LENGTH: 1187\r\n"); std::string payload_buffer("wfd_uibc_capABILITY: noNE\r\n\r\n"); Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); Driver::Parse(payload_buffer, message); ASSERT(message != NULL); ASSERT_EQUAL(message->header().cseq(), 2); ASSERT_EQUAL(message->header().content_type(), "tEXT/parameters"); ASSERT_EQUAL(message->header().content_length(), 1187); auto payload = ToPropertyMapPayload(message->payload()); ASSERT(payload); std::shared_ptr prop; ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::UIBCCapabilityPropertyType)); ASSERT(prop->is_none()); // TODO test insensitivity of triggers and method list return true; } static bool test_valid_get_parameter_reply_with_errors () { std::string header("RTSP/1.0 303 OK\r\n" "CSeq: 2\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 42\r\n\r\n"); std::string payload_buffer("wfd_audio_codecs: 415, 457\r\n" "wfd_I2C: 404\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); Driver::Parse(payload_buffer, message); ASSERT(message != NULL); wds::rtsp::Reply* reply = static_cast(message.get()); ASSERT(reply != NULL); ASSERT_EQUAL(reply->response_code(), 303); auto payload = ToPropertyErrorPayload(message->payload()); ASSERT(payload); std::shared_ptr error; ASSERT_EQUAL (payload->property_errors().size(), 2); ASSERT_NO_EXCEPTION(error = payload->GetPropertyError(wds::rtsp::AudioCodecsPropertyType)); ASSERT_EQUAL(error->error_codes().size(), 2); ASSERT_EQUAL(error->error_codes()[0], 415); ASSERT_EQUAL(error->error_codes()[1], 457); ASSERT_NO_EXCEPTION(error = payload->GetPropertyError(wds::rtsp::I2CPropertyType)); ASSERT_EQUAL(error->error_codes().size(), 1); ASSERT_EQUAL(error->error_codes()[0], 404); ASSERT_EQUAL(message->ToString(), header + payload_buffer); return true; } static bool test_valid_set_parameter () { std::string header("SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n" "CSeq: 3\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 275\r\n\r\n"); std::string payload_buffer("wfd_audio_codecs: AAC 00000001 00\r\n" "wfd_client_rtp_ports: RTP/AVP/UDP;unicast 19000 0 mode=play\r\n" "wfd_presentation_URL: rtsp://192.168.173.1/wfd1.0/streamid=0 none\r\n" "wfd_trigger_method: SETUP\r\n" "wfd_video_formats: 5A 00 02 04 00000020 00000000 00000000 00 0000 0000 11 none none\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_request()); Driver::Parse(payload_buffer, message); ASSERT(message != NULL); wds::rtsp::Request* request = wds::rtsp::ToRequest(message.get()); ASSERT_EQUAL(request->method(), wds::rtsp::Request::MethodSetParameter); ASSERT_EQUAL(request->request_uri(), "rtsp://localhost/wfd1.0"); ASSERT_EQUAL(request->header().cseq(), 3); ASSERT_EQUAL(request->header().content_length(), 275); ASSERT_EQUAL(request->header().require_wfd_support(), false); auto payload = ToPropertyMapPayload(message->payload()); ASSERT(payload); std::shared_ptr prop; ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::AudioCodecsPropertyType)); std::shared_ptr audio_codecs = std::static_pointer_cast (prop); ASSERT_EQUAL(audio_codecs->audio_codecs().size(), 1); ASSERT(test_audio_codec (audio_codecs->audio_codecs()[0], wds::AAC, 1, 0)); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::VideoFormatsPropertyType)); std::shared_ptr video_formats = std::static_pointer_cast (prop); ASSERT_EQUAL(video_formats->GetNativeFormat().rate_resolution, 11); ASSERT_EQUAL(video_formats->GetNativeFormat().type, 2); ASSERT_EQUAL(video_formats->GetH264Formats().size(), 1); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::ClientRTPPortsPropertyType)); std::shared_ptr client_rtp_ports = std::static_pointer_cast (prop); ASSERT_EQUAL(client_rtp_ports->rtp_port_0(), 19000); ASSERT_EQUAL(client_rtp_ports->rtp_port_1(), 0); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::TriggerMethodPropertyType)); std::shared_ptr trigger_method = std::static_pointer_cast (prop); ASSERT_EQUAL(trigger_method->method(), wds::rtsp::TriggerMethod::SETUP); ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::PresentationURLPropertyType)); ASSERT_EQUAL(request->ToString(), header + payload_buffer); return true; } static bool test_valid_set_parameter_url_with_port () { std::string header("SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n" "CSeq: 3\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 111\r\n\r\n"); std::string payload_buffer("wfd_presentation_URL: rtsp://192.168.173.1:3921/wfd1.0/streamid=0 rtsp://192.168.173.1:3922/wfd1.0/streamid=1\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_request()); Driver::Parse(payload_buffer, message); ASSERT(message != NULL); wds::rtsp::Request* request = wds::rtsp::ToRequest(message.get()); ASSERT_EQUAL(request->method(), wds::rtsp::Request::MethodSetParameter); ASSERT_EQUAL(request->request_uri(), "rtsp://localhost/wfd1.0"); ASSERT_EQUAL(request->header().cseq(), 3); ASSERT_EQUAL(request->header().content_length(), 111); ASSERT_EQUAL(request->header().require_wfd_support(), false); auto payload = ToPropertyMapPayload(message->payload()); ASSERT(payload); std::shared_ptr prop; ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::PresentationURLPropertyType)); ASSERT_EQUAL(request->ToString(), header + payload_buffer); return true; } static bool test_valid_set_parameter_with_all_ipv4_url () { std::string header("SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n" "CSeq: 3\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 61\r\n\r\n"); std::string payload_buffer("wfd_presentation_URL: rtsp://0.0.0.0/wfd1.0/streamid=0 none\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_request()); Driver::Parse(payload_buffer, message); ASSERT(message != NULL); wds::rtsp::Request* request = wds::rtsp::ToRequest(message.get()); ASSERT_EQUAL(request->method(), wds::rtsp::Request::MethodSetParameter); ASSERT_EQUAL(request->request_uri(), "rtsp://localhost/wfd1.0"); ASSERT_EQUAL(request->header().cseq(), 3); ASSERT_EQUAL(request->header().content_length(), 61); ASSERT_EQUAL(request->header().require_wfd_support(), false); auto payload = ToPropertyMapPayload(message->payload()); ASSERT(payload); std::shared_ptr prop; ASSERT_NO_EXCEPTION (prop = payload->GetProperty(wds::rtsp::PresentationURLPropertyType)); std::shared_ptr presentation_url = std::static_pointer_cast (prop); ASSERT_EQUAL(presentation_url->presentation_url_1(), "rtsp://0.0.0.0/wfd1.0/streamid=0"); ASSERT_EQUAL(request->ToString(), header + payload_buffer); return true; } static bool test_valid_setup () { std::string header("SETUP rtsp://10.82.24.140/wfd1.0/streamid=0 RTSP/1.0\r\n" "CSeq: 4\r\n" "Transport: RTP/AVP/UDP;unicast;client_port=19000\r\n" "User-Agent: SEC-WDH/ME29\r\n" "\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_request()); wds::rtsp::Request* request = wds::rtsp::ToRequest(message.get()); ASSERT_EQUAL(request->method(), wds::rtsp::Request::MethodSetup); ASSERT_EQUAL(request->request_uri(), "rtsp://10.82.24.140/wfd1.0/streamid=0"); ASSERT_EQUAL(request->header().cseq(), 4); ASSERT_EQUAL(request->header().content_length(), 0); ASSERT_EQUAL(request->header().require_wfd_support(), false); ASSERT_EQUAL(request->header().transport().client_port(), 19000); ASSERT_EQUAL(request->header().transport().client_supports_rtcp(), false); ASSERT_EQUAL(request->header().transport().server_port(), 0); ASSERT_EQUAL(request->header().transport().server_supports_rtcp(), false); ASSERT_EQUAL(request->ToString(), header); return true; } static bool test_valid_setup_reply () { std::string header("RTSP/1.0 200 OK\r\n" "CSeq: 4\r\n" "Session: 6B8B4567;timeout=30\r\n" "Transport: RTP/AVP/UDP;unicast;client_port=19000;server_port=5000-5001\r\n\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); wds::rtsp::Reply* reply = static_cast(message.get()); ASSERT(reply != NULL); ASSERT_EQUAL(reply->response_code(), 200); ASSERT_EQUAL(reply->header().cseq(), 4); ASSERT_EQUAL(reply->header().content_length(), 0); ASSERT_EQUAL(reply->header().session(), "6B8B4567"); ASSERT_EQUAL(reply->header().timeout(), 30); ASSERT_EQUAL(reply->header().transport().client_port(), 19000); ASSERT_EQUAL(reply->header().transport().client_supports_rtcp(), false); ASSERT_EQUAL(reply->header().transport().server_port(), 5000); ASSERT_EQUAL(reply->header().transport().server_supports_rtcp(), true); ASSERT_EQUAL(reply->ToString(), header); return true; } static bool test_valid_play () { std::string header("PLAY rtsp://localhost/wfd1.0 RTSP/1.0\r\n" "CSeq: 5\r\n" "Session: 6B8B4567\r\n" "User-Agent: SEC-WDH/ME29\r\n\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_request()); wds::rtsp::Request* request = wds::rtsp::ToRequest(message.get()); ASSERT_EQUAL(request->method(), wds::rtsp::Request::MethodPlay); ASSERT_EQUAL(request->request_uri(), "rtsp://localhost/wfd1.0"); ASSERT_EQUAL(request->header().cseq(), 5); ASSERT_EQUAL(request->header().content_length(), 0); ASSERT_EQUAL(request->header().require_wfd_support(), false); ASSERT_EQUAL(request->header().session(), "6B8B4567"); ASSERT_EQUAL(request->ToString(), header); return true; } static bool test_number_conversion_header() { std::string header("OPTIONS * RTSP/1.0\r\n" "CSeq: 92233720368547758079223372036854775807\r\n" "Require: org.wfa.wfd1.0\r\n\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message == NULL); return true; } static bool test_number_conversion_body() { std::string header("RTSP/1.0 200 OK\r\n" "CSeq: 2\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 101\r\n\r\n"); std::string payload_buffer("wfd_client_rtp_ports: RTP/AVP/UDP;unicast 92233720368547758079223372036854775807 0 mode=play\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); Driver::Parse(payload_buffer, message); ASSERT(message == NULL); return true; } static bool test_hex_number_conversion_body() { std::string header("RTSP/1.0 200 OK\r\n" "CSeq: 2\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 101\r\n\r\n"); std::string payload_buffer("wfd_audio_codecs: AAC 92233720368547758079223372036854775807 00\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); Driver::Parse(payload_buffer, message); ASSERT(message == NULL); return true; } static bool test_hex_number_conversion_body_2() { std::string header("RTSP/1.0 200 OK\r\n" "CSeq: 2\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 101\r\n\r\n"); std::string payload_buffer("wfd_audio_codecs: AAC FFFFFFFFFFFFFFFFF 00\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); Driver::Parse(payload_buffer, message); ASSERT(message == NULL); return true; } static bool test_number_conversion_in_errors () { std::string header("RTSP/1.0 303 OK\r\n" "CSeq: 0\r\n" "Content-Type: text/parameters\r\n" "Content-Length: 55\r\n\r\n"); std::unique_ptr message; Driver::Parse(header, message); ASSERT(message != NULL); ASSERT(message->is_reply()); std::string payload_buffer("wfd_audio_codecs: 92233720368547758079223372036854775807\r\n"); Driver::Parse(payload_buffer, message); ASSERT(message == NULL); return true; } int main(const int argc, const char **argv) { std::list tests; int failures = 0; // Add tests tests.push_back(test_valid_options); tests.push_back(test_valid_options_reply); tests.push_back(test_valid_get_parameter); tests.push_back(test_valid_get_parameter_reply); tests.push_back(test_valid_get_parameter_reply_with_all_none); tests.push_back(test_valid_get_parameter_reply_with_errors); tests.push_back(test_valid_setup_reply); tests.push_back(test_valid_set_parameter); tests.push_back(test_valid_set_parameter_url_with_port); tests.push_back(test_valid_set_parameter_with_all_ipv4_url); tests.push_back(test_valid_setup); tests.push_back(test_valid_play); tests.push_back(test_invalid_property_value); tests.push_back(test_case_insensitivity); tests.push_back(test_valid_extra_properties); tests.push_back(test_valid_extra_errors); tests.push_back(test_valid_extra_properties_in_get); tests.push_back(test_number_conversion_header); tests.push_back(test_number_conversion_body); tests.push_back(test_hex_number_conversion_body); tests.push_back(test_hex_number_conversion_body_2); tests.push_back(test_number_conversion_in_errors); // Run tests for (std::list::iterator it=tests.begin(); it!=tests.end(); ++it) { TestFunc test = *it; if (!test()) failures++; } if (failures > 0) { std::cout << std::endl << "Failed " << failures << " out of " << tests.size() << " tests" << std::endl; return 1; } std::cout << "Passed all " << tests.size() << " tests" << std::endl; return 0; } ================================================ FILE: libwds/rtsp/tests/wdsfuzzer.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2016 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include "libwds/rtsp/driver.h" #include "libwds/rtsp/message.h" #include "libwds/rtsp/reply.h" #include "libwds/rtsp/getparameter.h" using wds::rtsp::Driver; namespace { const char kTestHeaderCommand[] = "--header"; const char kTestPayloadRequestCommand[] = "--payload-request"; const char kTestPayloadReplyCommand[] = "--payload-reply"; const char kTestPayloadErrorCommand[] = "--payload-error"; const char kTestNumLinesCommand[] = "--num-lines"; const char kTestTestCaseCommand[] = "--test-case"; int PrintError(const char* program) { std::cerr << "Usage: " << program << " [--num-lines NUM | --test-case ABSOLUTE_PATH_FILE] [--header | --payload-request | --payload-reply | --payload-error]" << std::endl; std::cerr << "Example: " << program << " --num-lines 6 --header" << std::endl; std::cerr << "Example: " << program << " --test-case test-options-request.txt --header" << std::endl; return 1; } std::string GetBufferFromStdin(int num_lines) { std::string buffer, input; while(num_lines--) { getline(std::cin, input); buffer += input; if (num_lines) buffer += "\r\n"; } return buffer; } std::string GetBufferFromFile(const std::string& file) { std::string line, buffer; std::ifstream input_stream(file); if (input_stream.is_open()) { while (getline(input_stream, line)) buffer += line; input_stream.close(); } return buffer; } } // namespace int main(const int argc, const char **argv) { // Program name, number of lines to be read, type of message if (argc < 4) return PrintError(argv[0]); std::string buffer; if (strncmp(argv[1], kTestNumLinesCommand, strlen(kTestNumLinesCommand)) == 0) buffer = GetBufferFromStdin(atoi(argv[2])) + "\r\n\r\n"; else if (strncmp(argv[1], kTestTestCaseCommand, strlen(kTestTestCaseCommand)) == 0) buffer = GetBufferFromFile(argv[2]); else return PrintError(argv[0]); std::unique_ptr message; if (strcmp(argv[3], kTestHeaderCommand) == 0) { Driver::Parse(buffer, message); } else if (strcmp(argv[3], kTestPayloadReplyCommand) == 0) { message.reset(new wds::rtsp::Reply()); Driver::Parse(buffer, message); } else if (strcmp(argv[3], kTestPayloadRequestCommand) == 0) { message.reset(new wds::rtsp::GetParameter("rtsp://localhost/wfd1.0")); Driver::Parse(buffer, message); } else if (strcmp(argv[3], kTestPayloadErrorCommand) == 0) { message.reset(new wds::rtsp::Reply(303)); Driver::Parse(buffer, message); } else { return PrintError(argv[0]); } return 0; } ================================================ FILE: libwds/rtsp/transportheader.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/transportheader.h" #include "libwds/rtsp/constants.h" namespace wds { namespace rtsp { namespace { const char kTransport[] = "Transport: RTP/AVP/UDP;unicast;client_port="; const char kServerPort[] = ";server_port="; } TransportHeader::TransportHeader() : client_port_(0), server_port_(0), client_supports_rtcp_(false), server_supports_rtcp_(false) { } TransportHeader::~TransportHeader() { } unsigned int TransportHeader::client_port() const { return client_port_; } void TransportHeader::set_client_port(unsigned int client_port) { client_port_ = client_port; } unsigned int TransportHeader::server_port() const { return server_port_; } void TransportHeader::set_server_port(unsigned int server_port) { server_port_ = server_port; } bool TransportHeader::client_supports_rtcp() const { return client_supports_rtcp_; } void TransportHeader::set_client_supports_rtcp(bool client_supports_rtcp) { client_supports_rtcp_ = client_supports_rtcp; } bool TransportHeader::server_supports_rtcp() const { return server_supports_rtcp_; } void TransportHeader::set_server_supports_rtcp(bool server_supports_rtcp) { server_supports_rtcp_ = server_supports_rtcp; } std::string TransportHeader::ToString() const { std::string ret; if (client_port_ > 0) { ret += kTransport + std::to_string(client_port_); if (client_supports_rtcp_) ret += "-" + std::to_string(client_port_ + 1); if (server_port_ > 0) { ret += kServerPort + std::to_string(server_port_); if (server_supports_rtcp_) ret += "-" + std::to_string(server_port_ + 1); } ret += CRLF; } return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/transportheader.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_TRANSPORT_HEADER_H_ #define LIBWDS_RTSP_TRANSPORT_HEADER_H_ #include namespace wds { namespace rtsp { class TransportHeader { public: TransportHeader(); virtual ~TransportHeader(); unsigned int client_port() const; void set_client_port(unsigned int client_port); unsigned int server_port() const; void set_server_port(unsigned int server_port); bool client_supports_rtcp() const; void set_client_supports_rtcp(bool client_supports_rtcp); bool server_supports_rtcp() const; void set_server_supports_rtcp(bool server_supports_rtcp); std::string ToString() const; private: unsigned int client_port_; unsigned int server_port_; bool client_supports_rtcp_; bool server_supports_rtcp_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_TRANSPORT_HEADER_H_ ================================================ FILE: libwds/rtsp/triggermethod.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/triggermethod.h" namespace wds { namespace rtsp { namespace { const char* name[] = {MethodName::SETUP, MethodName::PAUSE, MethodName::TEARDOWN, MethodName::PLAY}; } TriggerMethod::TriggerMethod(TriggerMethod::Method method) : Property(TriggerMethodPropertyType), method_(method) { } TriggerMethod::~TriggerMethod() { } std::string TriggerMethod::ToString() const { std::string ret = PropertyName::wfd_trigger_method + std::string(SEMICOLON) + std::string(SPACE) + name[method()]; return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/triggermethod.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_TRIGGERMETHOD_H_ #define LIBWDS_RTSP_TRIGGERMETHOD_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class TriggerMethod : public Property { public: enum Method { SETUP, PAUSE, TEARDOWN, PLAY }; public: explicit TriggerMethod(TriggerMethod::Method method); ~TriggerMethod() override; TriggerMethod::Method method() const { return method_; } std::string ToString() const override; private: TriggerMethod::Method method_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_TRIGGERMETHOD_H_ ================================================ FILE: libwds/rtsp/uibccapability.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/uibccapability.h" namespace wds { namespace rtsp { namespace { const char kInputCategoryGeneric[] = "GENERIC"; const char kInputCategoryHIDC[] = "HIDC"; const char kInputCategoryList[] = "input_category_list="; const char* kInputCategories[] = { kInputCategoryGeneric, kInputCategoryHIDC }; const char kInputTypeKeyboard[] = "Keyboard"; const char kInputTypeMouse[] = "Mouse"; const char kInputTypeSingleTouch[] = "SingleTouch"; const char kInputTypeMultiTouch[] = "MultiTouch"; const char kInputTypeJoystick[] = "Joystick"; const char kInputTypeCamera[] = "Camera"; const char kInputTypeGesture[] = "Gesture"; const char kInputTypeRemoteControl[] = "RemoteControl"; const char kInputGenericCapabilityList[] = "generic_cap_list="; const char* kInputTypes[] = { kInputTypeKeyboard, kInputTypeMouse, kInputTypeSingleTouch, kInputTypeMultiTouch, kInputTypeJoystick, kInputTypeCamera, kInputTypeGesture, kInputTypeRemoteControl }; const char kInputPathInfrared[] = "Infrared"; const char kInputPathUSB[] = "USB"; const char kInputPathBT[] = "BT"; const char kInputPathZigbee[] = "Zigbee"; const char kInputPathWiFi[] = "Wi-Fi"; const char kInputPathNoSP[] = "No-SP"; const char kHIDCCapabilityList[] = "hidc_cap_list="; const char* kInputPaths[] = { kInputPathInfrared, kInputPathUSB, kInputPathBT, kInputPathZigbee, kInputPathWiFi, kInputPathNoSP }; } UIBCCapability::UIBCCapability() : Property(UIBCCapabilityPropertyType, true) { } UIBCCapability::UIBCCapability( const std::vector& input_categories, const std::vector& generic_capabilities, const std::vector hidc_capabilities, int tcp_port) : Property(UIBCCapabilityPropertyType), input_categories_(input_categories), generic_capabilities_(generic_capabilities), hidc_capabilities_(hidc_capabilities), tcp_port_(tcp_port) { } UIBCCapability::~UIBCCapability() { } std::string UIBCCapability::ToString() const { std::string ret; ret = PropertyName::wfd_uibc_capability + std::string(SEMICOLON) + std::string(SPACE); if (is_none()) return ret + NONE; ret += kInputCategoryList; auto inp_cat_i = input_categories_.begin(); auto inp_cat_end = input_categories_.end(); if (input_categories_.empty()) ret += NONE; while (inp_cat_i != inp_cat_end) { ret += kInputCategories[*inp_cat_i]; if(inp_cat_i != --input_categories_.end()) ret += std::string(",") + std::string(SPACE); else ret += std::string(";"); ++inp_cat_i; } ret += kInputGenericCapabilityList; auto gen_cap_i = generic_capabilities_.begin(); auto gen_cap_end = generic_capabilities_.end(); if (generic_capabilities_.empty()) ret += NONE; while (gen_cap_i != gen_cap_end) { ret += kInputTypes[*gen_cap_i]; if(gen_cap_i != --generic_capabilities_.end()) ret += std::string(",") + std::string(SPACE); else ret += std::string(";"); ++gen_cap_i; } ret += kHIDCCapabilityList; auto hidc_cap_i = hidc_capabilities_.begin(); auto hidc_cap_end = hidc_capabilities_.end(); if (hidc_capabilities_.empty()) ret += NONE; while (hidc_cap_i != hidc_cap_end) { ret += kInputTypes[(*hidc_cap_i).first] + std::string("/") + kInputPaths[(*hidc_cap_i).second]; if(hidc_cap_i != --hidc_capabilities_.end()) ret += std::string(",") + std::string(SPACE); else ret += std::string(";"); ++hidc_cap_i; } ret += tcp_port_ > 0 ? std::string("port=") + std::to_string(tcp_port_) : NONE; return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/uibccapability.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_UIBCCAPABILITY_H_ #define LIBWDS_RTSP_UIBCCAPABILITY_H_ #include "libwds/rtsp/property.h" #include #include namespace wds { namespace rtsp { class UIBCCapability: public Property { public: enum InputCategory { GENERIC, HIDC }; enum InputType { KEYBOARD, MOUSE, SINGLE_TOUCH, MULTI_TOUCH, JOYSTICK, CAMERA, GESTURE, REMOTE_CONTROL }; enum InputPath { INFRARED, USB, BT, ZIGBEE, WI_FI, NO_SP }; typedef std::pair DetailedCapability; public: UIBCCapability(); UIBCCapability(const std::vector& input_categories, const std::vector& generic_capabilities, const std::vector hidc_capabilities, int tcp_port); ~UIBCCapability() override; std::string ToString() const override; private: std::vector input_categories_; std::vector generic_capabilities_; std::vector hidc_capabilities_; int tcp_port_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_UIBCCAPABILITY_H_ ================================================ FILE: libwds/rtsp/uibcsetting.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/uibcsetting.h" namespace wds { namespace rtsp { namespace { const char enable[] = "enable"; const char disable[] = "disable"; } UIBCSetting::UIBCSetting(bool is_enabled) : Property(UIBCSettingPropertyType), is_enabled_(is_enabled) { } UIBCSetting::~UIBCSetting() { } std::string UIBCSetting::ToString() const { std::string ret = PropertyName::wfd_uibc_setting + std::string(SEMICOLON) + std::string(SPACE) + (is_enabled() ? enable : disable); return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/uibcsetting.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_UIBCSETTING_H_ #define LIBWDS_RTSP_UIBCSETTING_H_ #include "libwds/rtsp/property.h" namespace wds { namespace rtsp { class UIBCSetting : public Property { public: explicit UIBCSetting(bool is_enabled); ~UIBCSetting() override; bool is_enabled() const { return is_enabled_; } std::string ToString() const override; private: bool is_enabled_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_UIBCSETTING_H_ ================================================ FILE: libwds/rtsp/videoformats.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/rtsp/videoformats.h" #include #include "libwds/rtsp/macros.h" namespace wds { namespace rtsp { namespace { template unsigned int EnumListToMask(const std::vector& from) { unsigned int result = 0; for (auto item : from) { result = result | (1 << item); } return result; } } //namespace using wds::H264VideoFormat; using wds::H264VideoCodec; H264Codec::H264Codec(unsigned char profile, unsigned char level, unsigned int cea_support, unsigned int vesa_support, unsigned int hh_support, unsigned char latency, unsigned short min_slice_size, unsigned short slice_enc_params, unsigned char frame_rate_control_support, unsigned short max_hres, unsigned short max_vres) : profile(profile), level(level), cea_support(cea_support), vesa_support(vesa_support), hh_support(hh_support), latency(latency), min_slice_size(min_slice_size), slice_enc_params(slice_enc_params), frame_rate_control_support(frame_rate_control_support), max_hres(max_hres), max_vres(max_vres) {} H264Codec::H264Codec(const H264VideoFormat& format) : profile(1 << format.profile), level(1 << format.level), cea_support((format.type == CEA) ? 1 << format.rate_resolution : 0), vesa_support((format.type == VESA) ? 1 << format.rate_resolution : 0), hh_support((format.type == HH) ? 1 << format.rate_resolution : 0), latency(0), min_slice_size(0), slice_enc_params(0), frame_rate_control_support(0), max_hres(0), max_vres(0) { } H264Codec::H264Codec(const H264VideoCodec& format) : profile(1 << format.profile), level(1 << format.level), cea_support(format.cea_rr.to_ulong()), vesa_support(format.vesa_rr.to_ulong()), hh_support(format.hh_rr.to_ulong()), latency(0), min_slice_size(0), slice_enc_params(0), frame_rate_control_support(0), max_hres(0), max_vres(0) { } std::string H264Codec::ToString() const { std::string ret; MAKE_HEX_STRING_2(profile_str, profile); MAKE_HEX_STRING_2(level_str, level); MAKE_HEX_STRING_8(cea_support_str, cea_support); MAKE_HEX_STRING_8(vesa_support_str, vesa_support); MAKE_HEX_STRING_8(hh_support_str, hh_support); MAKE_HEX_STRING_2(latency_str, latency); MAKE_HEX_STRING_4(min_slice_size_str, min_slice_size); MAKE_HEX_STRING_4(slice_enc_params_str, slice_enc_params); MAKE_HEX_STRING_2(frame_rate_control_support_str, frame_rate_control_support); ret = profile_str + std::string(SPACE) + level_str + std::string(SPACE) + cea_support_str + std::string(SPACE) + vesa_support_str + std::string(SPACE) + hh_support_str + std::string(SPACE) + latency_str + std::string(SPACE) + min_slice_size_str + std::string(SPACE) + slice_enc_params_str + std::string(SPACE) + frame_rate_control_support_str + std::string(SPACE); if (max_hres > 0) { MAKE_HEX_STRING_4(max_hres_str, max_hres); ret += max_hres_str; } else { ret += NONE; } ret += std::string(SPACE); if (max_vres > 0) { MAKE_HEX_STRING_4(max_vres_str, max_vres); ret += max_vres_str; } else { ret += NONE; } return ret; } namespace { template EnumType MaskToEnum(ArgType from, EnumType biggest_value) { assert(from != 0); ArgType copy = from; unsigned result = 0; while ((copy & 1) == 0 && copy != 0) { copy = copy >> 1; ++result; } if (result > static_cast(biggest_value)) { assert(false); return biggest_value; } return static_cast(result); } template std::vector MaskToEnumList(ArgType from, EnumType biggest_value) { assert(from != 0); ArgType copy = from; unsigned enum_value = 0; std::vector result; while (copy != 0) { if ((copy & 1) != 0) { if (enum_value > static_cast(biggest_value)) break; result.push_back(static_cast(enum_value)); } copy = copy >> 1; ++enum_value; } return result; } inline H264Profile ToH264Profile(unsigned char profile) { return MaskToEnum(profile, CHP); } inline H264Level ToH264Level(unsigned char level) { return MaskToEnum(level, k4_2); } } // namespace H264VideoCodec H264Codec::ToH264VideoCodec() const { H264VideoCodec result; result.profile = ToH264Profile(profile); result.level = ToH264Level(level); result.cea_rr = RateAndResolutionsBitmap(cea_support); result.vesa_rr = RateAndResolutionsBitmap(vesa_support); result.hh_rr = RateAndResolutionsBitmap(hh_support); return result; } VideoFormats::VideoFormats() : Property(VideoFormatsPropertyType, true) { } VideoFormats::VideoFormats(NativeVideoFormat format, bool preferred_display_mode, const std::vector& h264_formats) : Property(VideoFormatsPropertyType), preferred_display_mode_(preferred_display_mode ? 1 : 0) { native_ = (format.rate_resolution << 3) | format.type; for(auto h264_format : h264_formats) h264_codecs_.push_back(H264Codec(h264_format)); } VideoFormats::VideoFormats(NativeVideoFormat format, bool preferred_display_mode, const std::vector& h264_formats) : Property(VideoFormatsPropertyType), preferred_display_mode_(preferred_display_mode ? 1 : 0) { native_ = (format.rate_resolution << 3) | format.type; for(auto h264_format : h264_formats) h264_codecs_.push_back(H264Codec(h264_format)); } VideoFormats::VideoFormats(unsigned char native, unsigned char preferred_display_mode, const H264Codecs& h264_codecs) : Property(VideoFormatsPropertyType), native_(native), preferred_display_mode_(preferred_display_mode), h264_codecs_(h264_codecs) { } VideoFormats::~VideoFormats() { } namespace { template NativeVideoFormat GetFormatFromIndex(unsigned index, EnumType biggest_value) { if (index <= static_cast(biggest_value)) return NativeVideoFormat(static_cast(index)); assert(false); return NativeVideoFormat(biggest_value); } } NativeVideoFormat VideoFormats::GetNativeFormat() const { unsigned index = native_ >> 3; unsigned selection_bits = native_ & 7; switch (selection_bits) { case 0: // 0b000 CEA return GetFormatFromIndex(index, CEA1920x1080p24); case 1: // 0b001 VESA return GetFormatFromIndex(index, VESA1920x1200p30); case 2: // 0b010 HH return GetFormatFromIndex(index, HH848x480p60); default: assert(false); break; } return NativeVideoFormat(CEA640x480p60); } std::vector VideoFormats::GetH264Formats() const { std::vector result; for (const auto& codec : h264_codecs_) PopulateVideoFormatList(codec.ToH264VideoCodec(), result); return result; } std::vector VideoFormats::GetH264VideoCodecs() const { std::vector result; for (const auto& codec : h264_codecs_) result.push_back(codec.ToH264VideoCodec()); return result; } std::string VideoFormats::ToString() const { std::string ret; ret = PropertyName::wfd_video_formats + std::string(SEMICOLON)+ std::string(SPACE); if (is_none()) return ret + NONE; MAKE_HEX_STRING_2(native, native_); MAKE_HEX_STRING_2(preferred_display_mode, preferred_display_mode_); ret += native + std::string(SPACE) + preferred_display_mode + std::string(SPACE); auto it = h264_codecs_.begin(); auto end = h264_codecs_.end(); while(it != end) { ret += (*it).ToString(); ++it; if (it != end) ret += ", "; } return ret; } } // namespace rtsp } // namespace wds ================================================ FILE: libwds/rtsp/videoformats.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_RTSP_VIDEOFORMATS_H_ #define LIBWDS_RTSP_VIDEOFORMATS_H_ #include "libwds/rtsp/property.h" #include "libwds/public/video_format.h" #include namespace wds { namespace rtsp { struct H264Codec { public: H264Codec(unsigned char profile, unsigned char level, unsigned int cea_support, unsigned int vesa_support, unsigned int hh_support, unsigned char latency, unsigned short min_slice_size, unsigned short slice_enc_params, unsigned char frame_rate_control_support, unsigned short max_hres, unsigned short max_vres); H264Codec(const H264VideoFormat& format); H264Codec(const H264VideoCodec& format); H264VideoCodec ToH264VideoCodec() const; std::string ToString() const; unsigned char profile; unsigned char level; unsigned int cea_support; unsigned int vesa_support; unsigned int hh_support; unsigned char latency; unsigned short min_slice_size; unsigned short slice_enc_params; unsigned char frame_rate_control_support; unsigned short max_hres; unsigned short max_vres; }; using H264Codecs = std::vector; class VideoFormats: public Property { public: VideoFormats(); VideoFormats(NativeVideoFormat format, bool preferred_display_mode, const std::vector& h264_formats); VideoFormats(NativeVideoFormat format, bool preferred_display_mode, const std::vector& h264_formats); VideoFormats(unsigned char native, unsigned char preferred_display_mode, const H264Codecs& h264_codecs); ~VideoFormats() override; NativeVideoFormat GetNativeFormat() const; std::vector GetH264Formats() const; std::vector GetH264VideoCodecs() const; std::string ToString() const override; private: unsigned char native_; unsigned char preferred_display_mode_; H264Codecs h264_codecs_; }; } // namespace rtsp } // namespace wds #endif // LIBWDS_RTSP_VIDEOFORMATS_H_ ================================================ FILE: libwds/sink/CMakeLists.txt ================================================ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fvisibility=hidden -fPIC") set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -std=c99 -Wall") include_directories ("${PROJECT_SOURCE_DIR}") add_library(wdssink OBJECT sink.cpp cap_negotiation_state.cpp init_state.cpp session_state.cpp streaming_state.cpp ) add_dependencies(wdssink wdsrtsp) ================================================ FILE: libwds/sink/cap_negotiation_state.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/sink/cap_negotiation_state.h" #include #include "libwds/public/media_manager.h" #include "libwds/rtsp/audiocodecs.h" #include "libwds/rtsp/clientrtpports.h" #include "libwds/rtsp/connectortype.h" #include "libwds/rtsp/contentprotection.h" #include "libwds/rtsp/coupledsink.h" #include "libwds/rtsp/displayedid.h" #include "libwds/rtsp/getparameter.h" #include "libwds/rtsp/formats3d.h" #include "libwds/rtsp/i2c.h" #include "libwds/rtsp/payload.h" #include "libwds/rtsp/presentationurl.h" #include "libwds/rtsp/propertyerrors.h" #include "libwds/rtsp/reply.h" #include "libwds/rtsp/setparameter.h" #include "libwds/rtsp/standbyresumecapability.h" #include "libwds/rtsp/triggermethod.h" #include "libwds/rtsp/uibccapability.h" #include "libwds/rtsp/videoformats.h" namespace wds { using rtsp::Message; using rtsp::Payload; using rtsp::Request; using rtsp::Reply; namespace sink { M3Handler::M3Handler(const InitParams& init_params) : MessageReceiver(init_params) { } std::unique_ptr M3Handler::HandleMessage(Message* message) { // FIXME : resolve clashes between wds exported and internal rtsp type names. //using namespace rtsp; auto received_payload = ToGetParameterPayload(message->payload()); if (!received_payload) return nullptr; auto reply = std::unique_ptr(new Reply(rtsp::STATUS_OK)); auto reply_payload = new rtsp::PropertyMapPayload(); for (const std::string& property : received_payload->properties()) { std::shared_ptr new_prop; if (property == GetPropertyName(rtsp::AudioCodecsPropertyType)){ // FIXME: declare that we support absolutely every audio codec/format, // but there should be a MediaManager API for it auto codec_lpcm = AudioCodec(LPCM, AudioModes(3), 0); auto codec_aac = AudioCodec(AAC, AudioModes(15), 0); auto codec_ac3 = AudioCodec(AC3, AudioModes(7), 0); std::vector codec_list; codec_list.push_back(codec_lpcm); codec_list.push_back(codec_aac); codec_list.push_back(codec_ac3); new_prop.reset(new rtsp::AudioCodecs(codec_list)); reply_payload->AddProperty(new_prop); } else if (property == GetPropertyName(rtsp::VideoFormatsPropertyType)){ new_prop.reset(new rtsp::VideoFormats(ToSinkMediaManager(manager_)->GetNativeVideoFormat(), false, ToSinkMediaManager(manager_)->GetSupportedH264VideoCodecs())); reply_payload->AddProperty(new_prop); } else if (property == GetPropertyName(rtsp::Video3DFormatsPropertyType)){ new_prop.reset(new rtsp::Formats3d()); reply_payload->AddProperty(new_prop); } else if (property == GetPropertyName(rtsp::ContentProtectionPropertyType)){ new_prop.reset(new rtsp::ContentProtection()); reply_payload->AddProperty(new_prop); } else if (property == GetPropertyName(rtsp::DisplayEdidPropertyType)){ new_prop.reset(new rtsp::DisplayEdid()); reply_payload->AddProperty(new_prop); } else if (property == GetPropertyName(rtsp::CoupledSinkPropertyType)){ new_prop.reset(new rtsp::CoupledSink()); reply_payload->AddProperty(new_prop); } else if (property == GetPropertyName(rtsp::ClientRTPPortsPropertyType)){ new_prop.reset(new rtsp::ClientRtpPorts( ToSinkMediaManager(manager_)->GetLocalRtpPorts().first, ToSinkMediaManager(manager_)->GetLocalRtpPorts().second)); reply_payload->AddProperty(new_prop); } else if (property == GetPropertyName(rtsp::I2CPropertyType)){ new_prop.reset(new rtsp::I2C(0)); reply_payload->AddProperty(new_prop); } else if (property == GetPropertyName(rtsp::UIBCCapabilityPropertyType)){ new_prop.reset(new rtsp::UIBCCapability()); reply_payload->AddProperty(new_prop); } else if (property == GetPropertyName(rtsp::ConnectorTypePropertyType)){ new_prop.reset(new rtsp::ConnectorType(ToSinkMediaManager(manager_)->GetConnectorType())); reply_payload->AddProperty(new_prop); } else if (property == GetPropertyName(rtsp::StandbyResumeCapabilityPropertyType)){ new_prop.reset(new rtsp::StandbyResumeCapability(false)); reply_payload->AddProperty(new_prop); } else { WDS_WARNING("** GET_PARAMETER: Ignoring unsupported property '%s'.", property.c_str()); } } reply->set_payload(std::unique_ptr(reply_payload)); return reply; } M4Handler::M4Handler(const InitParams& init_params) : MessageReceiver(init_params) { } std::unique_ptr M4Handler::HandleMessage(Message* message) { SinkMediaManager* sink_media_manager = ToSinkMediaManager(manager_); auto payload = ToPropertyMapPayload(message->payload()); if (!payload) { WDS_ERROR("Failed to obtain payload in M4 handler."); return nullptr; } auto presentation_url = static_cast(payload->GetProperty(rtsp::PresentationURLPropertyType).get()); if (presentation_url) { sink_media_manager->SetPresentationUrl(presentation_url->presentation_url_1()); } auto video_formats = static_cast(payload->GetProperty(rtsp::VideoFormatsPropertyType).get()); if (!video_formats) { WDS_ERROR("Failed to obtain 'wfd-video-formats' in M4 handler."); return nullptr; } const auto& selected_formats = video_formats->GetH264Formats(); if (selected_formats.size() != 1) { WDS_ERROR("Failed to obtain optimal video format from 'wfd-video-formats' in M4 handler."); return nullptr; } if (!sink_media_manager->SetOptimalVideoFormat(selected_formats[0])) { auto reply = std::unique_ptr(new Reply(rtsp::STATUS_SeeOther)); auto payload = new rtsp::PropertyErrorPayload(); std::vector error_codes = {rtsp::STATUS_UnsupportedMediaType}; auto property_errors = std::make_shared(rtsp::VideoFormatsPropertyType, error_codes); payload->AddPropertyError(property_errors); reply->set_payload(std::unique_ptr(payload)); return reply; } return std::unique_ptr(new Reply(rtsp::STATUS_OK)); } class M5Handler final : public MessageReceiver { public: M5Handler(const InitParams& init_params) : MessageReceiver(init_params) { } std::unique_ptr HandleMessage(Message* message) override { auto payload = ToPropertyMapPayload(message->payload()); if (!payload) { WDS_ERROR("Failed to obtain payload in M5 handler."); return nullptr; } auto property = static_cast(payload->GetProperty(rtsp::TriggerMethodPropertyType).get()); auto reply = std::unique_ptr(new Reply(rtsp::STATUS_OK)); reply->header().set_cseq(message->cseq()); if (property->method() != rtsp::TriggerMethod::SETUP) { reply->set_response_code(rtsp::STATUS_SeeOther); } return reply; } }; CapNegotiationState::CapNegotiationState(const InitParams &init_params) : MessageSequenceWithOptionalSetHandler(init_params) { AddSequencedHandler(make_ptr(new M3Handler(init_params))); AddSequencedHandler(make_ptr(new M4Handler(init_params))); AddSequencedHandler(make_ptr(new M5Handler(init_params))); AddOptionalHandler(make_ptr(new M3Handler(init_params))); AddOptionalHandler(make_ptr(new M4Handler(init_params))); } } // sink } // wds ================================================ FILE: libwds/sink/cap_negotiation_state.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_SINK_CAP_NEGOTIATION_STATE_H_ #define LIBWDS_SINK_CAP_NEGOTIATION_STATE_H_ #include "libwds/common/message_handler.h" namespace wds { namespace sink { // Capability negotiation state for RTSP sink. // Includes M3 and M4 messages handling class CapNegotiationState : public MessageSequenceWithOptionalSetHandler { public: CapNegotiationState(const InitParams& init_params); }; class M4Handler final : public MessageReceiver { public: M4Handler(const InitParams& init_params); std::unique_ptr HandleMessage(rtsp::Message* message) override; }; class M3Handler final : public MessageReceiver { public: M3Handler(const InitParams& init_params); std::unique_ptr HandleMessage(rtsp::Message* message) override; }; } // namespace sink } // namespace wds #endif // LIBWDS_SINK_CAP_NEGOTIATION_STATE_H_ ================================================ FILE: libwds/sink/init_state.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/sink/init_state.h" #include "libwds/rtsp/options.h" #include "libwds/rtsp/reply.h" namespace wds { namespace sink { using rtsp::Message; using rtsp::Request; using rtsp::Reply; class M1Handler final : public MessageReceiver { public: M1Handler(const InitParams& init_params, int& source_init_cseq) : MessageReceiver(init_params), source_init_cseq_(source_init_cseq) { } virtual std::unique_ptr HandleMessage(Message* message) override { source_init_cseq_ = message->cseq(); auto reply = std::unique_ptr(new Reply(rtsp::STATUS_OK)); std::vector supported_methods; supported_methods.push_back(rtsp::ORG_WFA_WFD_1_0); supported_methods.push_back(rtsp::GET_PARAMETER); supported_methods.push_back(rtsp::SET_PARAMETER); reply->header().set_supported_methods(supported_methods); return reply; } private: int& source_init_cseq_; }; class M2Handler final : public SequencedMessageSender { public: M2Handler(const InitParams& init_params, int& source_init_cseq) : SequencedMessageSender(init_params), source_init_cseq_(source_init_cseq) { } private: virtual std::unique_ptr CreateMessage() override { auto options = new rtsp::Options("*"); options->header().set_cseq(sender_->GetNextCSeq(&source_init_cseq_)); options->header().set_require_wfd_support(true); return std::unique_ptr(options); } virtual bool HandleReply(Reply* reply) override { const rtsp::Header& header = reply->header(); if (reply->response_code() == rtsp::STATUS_OK && header.has_method(rtsp::Method::ORG_WFA_WFD_1_0) && header.has_method(rtsp::Method::GET_PARAMETER) && header.has_method(rtsp::Method::SET_PARAMETER) && header.has_method(rtsp::Method::SETUP) && header.has_method(rtsp::Method::PLAY) && header.has_method(rtsp::Method::TEARDOWN) && header.has_method(rtsp::Method::PAUSE)) { return true; } return false; } int& source_init_cseq_; }; InitState::InitState(const InitParams& init_params) : MessageSequenceHandler(init_params), source_init_cseq_(0) { AddSequencedHandler(make_ptr(new M1Handler(init_params, source_init_cseq_))); AddSequencedHandler(make_ptr(new M2Handler(init_params, source_init_cseq_))); } } // sink } // wds ================================================ FILE: libwds/sink/init_state.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_SINK_INIT_STATE_H_ #define LIBWDS_SINK_INIT_STATE_H_ #include "libwds/common/message_handler.h" namespace wds { namespace sink { // Inital state for RTSP sink. // Includes M1 and M2 messages handling class InitState : public MessageSequenceHandler { public: InitState(const InitParams& init_params); private: int source_init_cseq_; }; } // sink } // wds #endif // LIBWDS_SINK_INIT_STATE_H_ ================================================ FILE: libwds/sink/session_state.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/sink/session_state.h" #include "libwds/public/media_manager.h" #include "libwds/rtsp/play.h" #include "libwds/rtsp/reply.h" #include "libwds/rtsp/setup.h" #include "libwds/rtsp/transportheader.h" #include "libwds/sink/cap_negotiation_state.h" #include "libwds/sink/streaming_state.h" namespace wds { using rtsp::Message; using rtsp::Request; using rtsp::Reply; namespace sink { M16Handler::M16Handler(const InitParams& init_params, unsigned& keep_alive_timer) : MessageReceiver(init_params), keep_alive_timer_(keep_alive_timer) { } bool M16Handler::HandleTimeoutEvent(unsigned timer_id) const { return timer_id == keep_alive_timer_; } std::unique_ptr M16Handler::HandleMessage(Message* message) { // Reset keep alive timer; sender_->ReleaseTimer(keep_alive_timer_); keep_alive_timer_ = sender_->CreateTimer(60); return std::unique_ptr(new Reply(rtsp::STATUS_OK)); } M6Handler::M6Handler(const InitParams& init_params, unsigned& keep_alive_timer) : SequencedMessageSender(init_params), keep_alive_timer_(keep_alive_timer) {} std::unique_ptr M6Handler::CreateMessage() { auto setup = new rtsp::Setup(ToSinkMediaManager(manager_)->GetPresentationUrl()); auto transport = new rtsp::TransportHeader(); // we assume here that there is no coupled secondary sink transport->set_client_port(ToSinkMediaManager(manager_)->GetLocalRtpPorts().first); setup->header().set_transport(transport); setup->header().set_cseq(sender_->GetNextCSeq()); setup->header().set_require_wfd_support(true); return std::unique_ptr(setup); } bool M6Handler::HandleReply(Reply* reply) { const std::string& session_id = reply->header().session(); if(reply->response_code() == rtsp::STATUS_OK && !session_id.empty()) { ToSinkMediaManager(manager_)->SetSessionId(session_id); // FIXME : take timeout value from session. keep_alive_timer_ = sender_->CreateTimer(60); return true; } return false; } class M7Handler final : public SequencedMessageSender { public: using SequencedMessageSender::SequencedMessageSender; private: std::unique_ptr CreateMessage() override { rtsp::Play* play = new rtsp::Play(ToSinkMediaManager(manager_)->GetPresentationUrl()); play->header().set_session(manager_->GetSessionId()); play->header().set_cseq(sender_->GetNextCSeq()); play->header().set_require_wfd_support(true); return std::unique_ptr(play); } bool HandleReply(Reply* reply) override { return (reply->response_code() == rtsp::STATUS_OK); } }; SessionState::SessionState(const InitParams& init_params, MessageHandlerPtr m6_handler, MessageHandlerPtr m16_handler) : MessageSequenceWithOptionalSetHandler(init_params) { AddSequencedHandler(m6_handler); AddSequencedHandler(make_ptr(new M7Handler(init_params))); AddOptionalHandler(make_ptr(new M3Handler(init_params))); AddOptionalHandler(make_ptr(new M4Handler(init_params))); AddOptionalHandler(make_ptr(new TeardownHandler(init_params))); AddOptionalHandler(m16_handler); } } // namespace sink } // namespace wds ================================================ FILE: libwds/sink/session_state.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_SINK_SESSION_STATE_H_ #define LIBWDS_SINK_SESSION_STATE_H_ #include "libwds/common/message_handler.h" namespace wds { namespace sink { class M6Handler final : public SequencedMessageSender { public: M6Handler(const InitParams& init_params, unsigned& keep_alive_timer); private: std::unique_ptr CreateMessage() override; bool HandleReply(rtsp::Reply* reply) override; unsigned& keep_alive_timer_; }; class M16Handler final : public MessageReceiver { public: M16Handler(const InitParams& init_params, unsigned& keep_alive_timer); private: bool HandleTimeoutEvent(unsigned timer_id) const override; std::unique_ptr HandleMessage(rtsp::Message* message) override; unsigned& keep_alive_timer_; }; // WFD session state for RTSP sink. // Includes M6, M7, M8 messages handling and optionally can handle M3, M4, M16 class SessionState : public MessageSequenceWithOptionalSetHandler { public: SessionState(const InitParams& init_params, MessageHandlerPtr m6_handler, MessageHandlerPtr m16_handler); }; } // sink } // wds #endif // LIBWDS_SINK_SESSION_STATE_H_ ================================================ FILE: libwds/sink/sink.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/public/sink.h" #include "libwds/common/message_handler.h" #include "libwds/common/rtsp_input_handler.h" #include "libwds/public/wds_export.h" #include "libwds/rtsp/pause.h" #include "libwds/rtsp/play.h" #include "libwds/rtsp/teardown.h" #include "libwds/rtsp/triggermethod.h" #include "libwds/public/media_manager.h" #include "libwds/sink/cap_negotiation_state.h" #include "libwds/sink/init_state.h" #include "libwds/sink/session_state.h" #include "libwds/sink/streaming_state.h" namespace wds { using rtsp::Message; using rtsp::Request; using rtsp::Reply; namespace { // todo: check mandatory parameters for each message bool InitializeRequestId(Request* request) { Request::ID id = Request::UNKNOWN; switch(request->method()) { case Request::MethodOptions: id = Request::M1; break; case Request::MethodGetParameter: if (auto payload = rtsp::ToGetParameterPayload(request->payload())) { if (!payload->properties().empty()) id = Request::M3; } else { id = Request::M16; } break; case Request::MethodSetParameter: if (auto payload = rtsp::ToPropertyMapPayload(request->payload())) { if (payload->HasProperty(rtsp::PresentationURLPropertyType)) id = Request::M4; else if (payload->HasProperty(rtsp::AVFormatChangeTimingPropertyType)) id = Request::M4; else if (payload->HasProperty(rtsp::TriggerMethodPropertyType)) id = Request::M5; break; } default: WDS_ERROR("Failed to identify the received message"); return false; } request->set_id(id); return true; } } class SinkStateMachine : public MessageSequenceHandler { public: SinkStateMachine(const InitParams& init_params) : MessageSequenceHandler(init_params), keep_alive_timer_(0) { auto m6_handler = make_ptr(new sink::M6Handler(init_params, keep_alive_timer_)); auto m16_handler = make_ptr(new sink::M16Handler(init_params, keep_alive_timer_)); AddSequencedHandler(make_ptr(new sink::InitState(init_params))); AddSequencedHandler(make_ptr(new sink::CapNegotiationState(init_params))); AddSequencedHandler(make_ptr(new sink::SessionState(init_params, m6_handler, m16_handler))); AddSequencedHandler(make_ptr(new sink::StreamingState(init_params, m16_handler))); } SinkStateMachine(Peer::Delegate* sender, SinkMediaManager* mng) : SinkStateMachine({sender, mng, this}) {} private: unsigned keep_alive_timer_; }; class SinkImpl final : public Sink, public RTSPInputHandler, public MessageHandler::Observer { public: SinkImpl(Delegate* delegate, SinkMediaManager* mng); private: // Sink implementation. void Start() override; void Reset() override; void RTSPDataReceived(const std::string& message) override; bool Teardown() override; bool Play() override; bool Pause() override; // RTSPInputHandler void MessageParsed(std::unique_ptr message) override; // public MessageHandler::Observer void OnCompleted(MessageHandlerPtr handler) override; void OnError(MessageHandlerPtr handler) override; void OnTimerEvent(unsigned timer_id) override; bool HandleCommand(std::unique_ptr command); template std::unique_ptr CreateCommand(); void ResetAndTeardownMedia(); std::shared_ptr state_machine_; Delegate* delegate_; SinkMediaManager* manager_; }; SinkImpl::SinkImpl(Delegate* delegate, SinkMediaManager* mng) : state_machine_(new SinkStateMachine({delegate, mng, this})), delegate_(delegate), manager_(mng) { } void SinkImpl::Start() { state_machine_->Start(); } void SinkImpl::Reset() { state_machine_->Reset(); } void SinkImpl::RTSPDataReceived(const std::string& message) { AddInput(message); } template std::unique_ptr SinkImpl::CreateCommand() { auto message = new WfdMessage(manager_->GetPresentationUrl()); message->header().set_session(manager_->GetSessionId()); message->header().set_cseq(delegate_->GetNextCSeq()); message->set_id(id); return std::unique_ptr(message); } bool SinkImpl::HandleCommand(std::unique_ptr command) { if (manager_->GetSessionId().empty() || manager_->GetPresentationUrl().empty()) return false; if (!state_machine_->CanSend(command.get())) return false; state_machine_->Send(std::move(command)); return true; } bool SinkImpl::Teardown() { return HandleCommand(CreateCommand()); } bool SinkImpl::Play() { return HandleCommand(CreateCommand()); } bool SinkImpl::Pause() { return HandleCommand(CreateCommand()); } void SinkImpl::MessageParsed(std::unique_ptr message) { if (message->is_request() && !InitializeRequestId(ToRequest(message.get()))) { WDS_ERROR("Cannot identify the received message"); return; } if (!state_machine_->CanHandle(message.get())) { WDS_ERROR("Cannot handle the received message with Id: %d", ToRequest(message.get())->id()); return; } state_machine_->Handle(std::move(message)); } void SinkImpl::ResetAndTeardownMedia() { manager_->Teardown(); state_machine_->Reset(); } void SinkImpl::OnCompleted(MessageHandlerPtr handler) { assert(handler == state_machine_); ResetAndTeardownMedia(); } void SinkImpl::OnError(MessageHandlerPtr handler) { assert(handler == state_machine_); ResetAndTeardownMedia(); } void SinkImpl::OnTimerEvent(unsigned timer_id) { if (state_machine_->HandleTimeoutEvent(timer_id)) state_machine_->Reset(); } Sink* Sink::Create(Delegate* delegate, SinkMediaManager* mng) { return new SinkImpl(delegate, mng); } } // namespace wds ================================================ FILE: libwds/sink/streaming_state.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/sink/streaming_state.h" #include "libwds/public/media_manager.h" #include "libwds/rtsp/pause.h" #include "libwds/rtsp/play.h" #include "libwds/rtsp/reply.h" #include "libwds/rtsp/teardown.h" #include "libwds/rtsp/triggermethod.h" #include "libwds/sink/cap_negotiation_state.h" #include "libwds/sink/session_state.h" namespace wds { using rtsp::Message; using rtsp::Request; using rtsp::Reply; using rtsp::TriggerMethod; namespace sink { template class M5Handler final : public MessageReceiver { public: explicit M5Handler(const InitParams& init_params) : MessageReceiver(init_params) { } bool CanHandle(Message* message) const override { if (!MessageReceiver::CanHandle(message)) return false; auto payload = ToPropertyMapPayload(message->payload()); if (!payload) { WDS_ERROR("Failed to obtain payload in M5 handler."); return false; } auto property = static_cast( payload->GetProperty(rtsp::TriggerMethodPropertyType).get()); return method == property->method(); } std::unique_ptr HandleMessage(Message* message) override { return std::unique_ptr(new Reply()); } }; class M7Sender final : public SequencedMessageSender { public: using SequencedMessageSender::SequencedMessageSender; private: std::unique_ptr CreateMessage() override { rtsp::Play* play = new rtsp::Play(ToSinkMediaManager(manager_)->GetPresentationUrl()); play->header().set_session(manager_->GetSessionId()); play->header().set_cseq (sender_->GetNextCSeq()); return std::unique_ptr(play); } bool HandleReply(Reply* reply) override { if (reply->response_code() == rtsp::STATUS_OK) { manager_->Play(); return true; } return false; } }; class PlayHandler : public MessageSequenceHandler { public: explicit PlayHandler(const InitParams& init_params) : MessageSequenceHandler(init_params) { AddSequencedHandler(make_ptr(new M5Handler(init_params))); AddSequencedHandler(make_ptr(new M7Sender(init_params))); } }; class M8Sender final : public SequencedMessageSender { public: using SequencedMessageSender::SequencedMessageSender; private: std::unique_ptr CreateMessage() override { rtsp::Teardown* teardown = new rtsp::Teardown(ToSinkMediaManager(manager_)->GetPresentationUrl()); teardown->header().set_session(manager_->GetSessionId()); teardown->header().set_cseq(sender_->GetNextCSeq()); return std::unique_ptr(teardown); } bool HandleReply(Reply* reply) override { if (!manager_->GetSessionId().empty() && (reply->response_code() == rtsp::STATUS_OK)) { manager_->Teardown(); return true; } return false; } }; TeardownHandler::TeardownHandler(const InitParams& init_params) : MessageSequenceHandler(init_params) { AddSequencedHandler(make_ptr(new M5Handler(init_params))); AddSequencedHandler(make_ptr(new M8Sender(init_params))); } class M9Sender final : public SequencedMessageSender { public: using SequencedMessageSender::SequencedMessageSender; private: std::unique_ptr CreateMessage() override { rtsp::Pause* pause = new rtsp::Pause(ToSinkMediaManager(manager_)->GetPresentationUrl()); pause->header().set_session(manager_->GetSessionId()); pause->header().set_cseq(sender_->GetNextCSeq()); return std::unique_ptr(pause); } bool HandleReply(Reply* reply) override { if (reply->response_code() == rtsp::STATUS_OK) { manager_->Pause(); return true; } return false; } }; class PauseHandler : public MessageSequenceHandler { public: explicit PauseHandler(const InitParams& init_params) : MessageSequenceHandler(init_params) { AddSequencedHandler(make_ptr(new M5Handler(init_params))); AddSequencedHandler(make_ptr(new M9Sender(init_params))); } }; class M7SenderOptional final : public OptionalMessageSender { public: M7SenderOptional(const InitParams& init_params) : OptionalMessageSender(init_params) { } private: bool HandleReply(Reply* reply) override { if (reply->response_code() == rtsp::STATUS_OK) { manager_->Play(); return true; } return false; } bool CanSend(Message* message) const override { if (OptionalMessageSender::CanSend(message) && manager_->IsPaused()) return true; return false; } }; class M8SenderOptional final : public OptionalMessageSender { public: M8SenderOptional(const InitParams& init_params) : OptionalMessageSender(init_params) { } private: bool HandleReply(Reply* reply) override { // todo: if successfull, switch to init state if (reply->response_code() == rtsp::STATUS_OK) { manager_->Teardown(); return true; } return false; } }; class M9SenderOptional final : public OptionalMessageSender { public: M9SenderOptional(const InitParams& init_params) : OptionalMessageSender(init_params) { } private: bool HandleReply(Reply* reply) override { if (reply->response_code() == rtsp::STATUS_OK) { manager_->Pause(); return true; } return false; } bool CanSend(Message* message) const override { if (OptionalMessageSender::CanSend(message) && !manager_->IsPaused()) return true; return false; } }; StreamingState::StreamingState(const InitParams& init_params, MessageHandlerPtr m16_handler) : MessageSequenceWithOptionalSetHandler(init_params) { AddSequencedHandler(make_ptr(new TeardownHandler(init_params))); AddOptionalHandler(make_ptr(new PlayHandler(init_params))); AddOptionalHandler(make_ptr(new PauseHandler(init_params))); AddOptionalHandler(make_ptr(new M3Handler(init_params))); AddOptionalHandler(make_ptr(new M4Handler(init_params))); // optional senders that handle sending play, pause and teardown AddOptionalHandler(make_ptr(new M7SenderOptional(init_params))); AddOptionalHandler(make_ptr(new M8SenderOptional(init_params))); AddOptionalHandler(make_ptr(new M9SenderOptional(init_params))); AddOptionalHandler(m16_handler); } } // sink } // wds ================================================ FILE: libwds/sink/streaming_state.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_SINK_STREAMING_STATE_H_ #define LIBWDS_SINK_STREAMING_STATE_H_ #include "libwds/common/message_handler.h" namespace wds { namespace sink { // Streaming state for RTSP sink. // Includes M8 message handling and optionally can handle M3, M4, M7 and M9 class StreamingState : public MessageSequenceWithOptionalSetHandler { public: StreamingState(const InitParams& init_params, MessageHandlerPtr m16_handler); }; class TeardownHandler : public MessageSequenceHandler { public: explicit TeardownHandler(const InitParams& init_params); }; } // sink } // wds #endif // LIBWDS_SINK_STREAMING_STATE_H_ ================================================ FILE: libwds/source/CMakeLists.txt ================================================ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fvisibility=hidden -fPIC") set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -std=c99 -Wall") include_directories ("${PROJECT_SOURCE_DIR}") add_library(wdssource OBJECT source.cpp cap_negotiation_state.cpp init_state.cpp session_state.cpp streaming_state.cpp) add_dependencies(wdssource wdsrtsp) ================================================ FILE: libwds/source/cap_negotiation_state.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/source/cap_negotiation_state.h" #include "libwds/rtsp/audiocodecs.h" #include "libwds/rtsp/clientrtpports.h" #include "libwds/rtsp/getparameter.h" #include "libwds/rtsp/payload.h" #include "libwds/rtsp/presentationurl.h" #include "libwds/rtsp/reply.h" #include "libwds/rtsp/setparameter.h" #include "libwds/rtsp/videoformats.h" #include "libwds/public/media_manager.h" namespace wds { using rtsp::AudioCodecs; using rtsp::ClientRtpPorts; using rtsp::GetParameter; using rtsp::Message; using rtsp::Payload; using rtsp::Property; using rtsp::Request; using rtsp::Reply; using rtsp::SetParameter; using rtsp::VideoFormats; namespace source { class M3Handler final : public SequencedMessageSender { public: using SequencedMessageSender::SequencedMessageSender; private: std::unique_ptr CreateMessage() override; bool HandleReply(Reply* reply) override; }; class M4Handler final : public SequencedMessageSender { public: using SequencedMessageSender::SequencedMessageSender; private: std::unique_ptr CreateMessage() override; bool HandleReply(Reply* reply) override; }; std::unique_ptr M3Handler::CreateMessage() { GetParameter* get_param = new GetParameter("rtsp://localhost/wfd1.0"); get_param->header().set_cseq(sender_->GetNextCSeq()); std::vector props; SessionType media_type = ToSourceMediaManager(manager_)->GetSessionType(); if (media_type & VideoSession) props.push_back("wfd_video_formats"); if (media_type & AudioSession) props.push_back("wfd_audio_codecs"); props.push_back("wfd_client_rtp_ports"); get_param->set_payload( std::unique_ptr(new rtsp::GetParameterPayload(props))); return std::unique_ptr(get_param); } bool M3Handler::HandleReply(Reply* reply) { if (reply->response_code() != rtsp::STATUS_OK) return false; SourceMediaManager* source_manager = ToSourceMediaManager(manager_); auto payload = ToPropertyMapPayload(reply->payload()); if (!payload){ WDS_ERROR("Failed to obtain payload from reply."); return false; } auto property = payload->GetProperty(rtsp::ClientRTPPortsPropertyType); auto ports = static_cast(property.get()); if (!ports){ WDS_ERROR("Failed to obtain RTP ports from source."); return false; } source_manager->SetSinkRtpPorts(ports->rtp_port_0(), ports->rtp_port_1()); auto video_formats = static_cast( payload->GetProperty(rtsp::VideoFormatsPropertyType).get()); auto audio_codecs = static_cast( payload->GetProperty(rtsp::AudioCodecsPropertyType).get()); if (!video_formats && (source_manager->GetSessionType() & VideoSession)) { WDS_ERROR("Failed to obtain WFD_VIDEO_FORMATS property"); return false; } if (!audio_codecs && (source_manager->GetSessionType() & AudioSession)) { WDS_ERROR("Failed to obtain WFD_AUDIO_CODECS property"); return false; } if (video_formats && !source_manager->InitOptimalVideoFormat( video_formats->GetNativeFormat(), video_formats->GetH264VideoCodecs())) { WDS_ERROR("Cannot initalize optimal video format from the supported by sink."); return false; } if (audio_codecs && !source_manager->InitOptimalAudioFormat( audio_codecs->audio_codecs())) { WDS_ERROR("Cannot initalize optimal audio format from the supported by sink."); return false; } return true; } std::unique_ptr M4Handler::CreateMessage() { SetParameter* set_param = new SetParameter("rtsp://localhost/wfd1.0"); set_param->header().set_cseq(sender_->GetNextCSeq()); SourceMediaManager* source_manager = ToSourceMediaManager(manager_); const auto& ports = source_manager->GetSinkRtpPorts(); auto payload = new rtsp::PropertyMapPayload(); payload->AddProperty( std::shared_ptr(new ClientRtpPorts(ports.first, ports.second))); std::string presentation_Url_1 = "rtsp://" + sender_->GetLocalIPAddress() + "/wfd1.0/streamid=0"; payload->AddProperty( std::shared_ptr(new rtsp::PresentationUrl(presentation_Url_1, ""))); if (source_manager->GetSessionType() & VideoSession) { payload->AddProperty( std::shared_ptr(new VideoFormats( NativeVideoFormat(), // Should be all zeros. false, {source_manager->GetOptimalVideoFormat()}))); } if (source_manager->GetSessionType() & AudioSession) { payload->AddProperty( std::shared_ptr(new AudioCodecs({source_manager->GetOptimalAudioFormat()}))); } set_param->set_payload(std::unique_ptr(payload)); return std::unique_ptr(set_param); } bool M4Handler::HandleReply(Reply* reply) { return (reply->response_code() == rtsp::STATUS_OK); } CapNegotiationState::CapNegotiationState(const InitParams &init_params) : MessageSequenceHandler(init_params) { AddSequencedHandler(make_ptr(new M3Handler(init_params))); AddSequencedHandler(make_ptr(new M4Handler(init_params))); } CapNegotiationState::~CapNegotiationState() { } } // namespace source } // namespace wds ================================================ FILE: libwds/source/cap_negotiation_state.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_SOURCE_CAP_NEGOTIATION_STATE_H_ #define LIBWDS_SOURCE_CAP_NEGOTIATION_STATE_H_ #include "libwds/common/message_handler.h" namespace wds { namespace source { // Capability negotiation state for RTSP source. // Includes M3 and M4 messages handling class CapNegotiationState : public MessageSequenceHandler { public: CapNegotiationState(const InitParams& init_params); ~CapNegotiationState() override; }; } // source } // wds #endif // LIBWDS_SOURCE_CAP_NEGOTIATION_STATE_H_ ================================================ FILE: libwds/source/init_state.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/source/init_state.h" #include "libwds/rtsp/options.h" #include "libwds/rtsp/reply.h" namespace wds { using rtsp::Message; using rtsp::Request; using rtsp::Reply; namespace source { class M1Handler final : public SequencedMessageSender { public: using SequencedMessageSender::SequencedMessageSender; private: std::unique_ptr CreateMessage() override { rtsp::Options* options = new rtsp::Options("*"); options->header().set_cseq(sender_->GetNextCSeq()); options->header().set_require_wfd_support(true); return std::unique_ptr(options); } bool HandleReply(Reply* reply) override { return (reply->response_code() == rtsp::STATUS_OK); } }; class M2Handler final : public MessageReceiver { public: M2Handler(const InitParams& init_params) : MessageReceiver(init_params) { } std::unique_ptr HandleMessage( Message* message) override { auto reply = std::unique_ptr(new Reply(rtsp::STATUS_OK)); std::vector supported_methods; supported_methods.push_back(rtsp::ORG_WFA_WFD_1_0); supported_methods.push_back(rtsp::GET_PARAMETER); supported_methods.push_back(rtsp::SET_PARAMETER); supported_methods.push_back(rtsp::PLAY); supported_methods.push_back(rtsp::PAUSE); supported_methods.push_back(rtsp::SETUP); supported_methods.push_back(rtsp::TEARDOWN); reply->header().set_supported_methods(supported_methods); return reply; } }; InitState::InitState(const InitParams& init_params) : MessageSequenceHandler(init_params) { AddSequencedHandler(make_ptr(new M1Handler(init_params))); AddSequencedHandler(make_ptr(new M2Handler(init_params))); } InitState::~InitState() { } } // source } // wds ================================================ FILE: libwds/source/init_state.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_SOURCE_INIT_STATE_H_ #define LIBWDS_SOURCE_INIT_STATE_H_ #include "libwds/common/message_handler.h" namespace wds { namespace source { // Inital state for RTSP source. // Includes M1 and M2 messages handling class InitState : public MessageSequenceHandler { public: InitState(const InitParams& init_params); ~InitState() override; }; } // source } // wds #endif // LIBWDS_SOURCE_INIT_STATE_H_ ================================================ FILE: libwds/source/session_state.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/source/session_state.h" #include "libwds/public/media_manager.h" #include "libwds/source/cap_negotiation_state.h" #include "libwds/rtsp/reply.h" #include "libwds/rtsp/setparameter.h" #include "libwds/rtsp/triggermethod.h" namespace wds { using rtsp::Message; using rtsp::Payload; using rtsp::Request; using rtsp::Reply; namespace source { class M5Handler final : public SequencedMessageSender { public: using SequencedMessageSender::SequencedMessageSender; private: std::unique_ptr CreateMessage() override { rtsp::SetParameter* set_param = new rtsp::SetParameter("rtsp://localhost/wfd1.0"); set_param->header().set_cseq(sender_->GetNextCSeq()); auto payload = new rtsp::PropertyMapPayload(); payload->AddProperty( std::shared_ptr(new rtsp::TriggerMethod(rtsp::TriggerMethod::SETUP))); set_param->set_payload(std::unique_ptr(payload)); return std::unique_ptr(set_param); } bool HandleReply(Reply* reply) override { return (reply->response_code() == rtsp::STATUS_OK); } }; class M6Handler final : public MessageReceiver { public: M6Handler(const InitParams& init_params, unsigned& timer_id) : MessageReceiver(init_params), keep_alive_timer_(timer_id) { } std::unique_ptr HandleMessage( Message* message) override { auto reply = std::unique_ptr(new Reply(rtsp::STATUS_OK)); reply->header().set_session(manager_->GetSessionId()); reply->header().set_timeout(kDefaultKeepAliveTimeout); auto transport = new rtsp::TransportHeader(); // we assume here that there is no coupled secondary sink transport->set_client_port(ToSourceMediaManager(manager_)->GetSinkRtpPorts().first); transport->set_server_port(ToSourceMediaManager(manager_)->GetLocalRtpPort()); reply->header().set_transport(transport); return reply; } void Handle(std::unique_ptr message) override { MessageReceiver::Handle(std::move(message)); keep_alive_timer_ = sender_->CreateTimer(kDefaultTimeoutValue); } unsigned& keep_alive_timer_; }; M7Handler::M7Handler(const InitParams& init_params) : MessageReceiver(init_params) { } std::unique_ptr M7Handler::HandleMessage( Message* message) { if (!manager_->IsPaused()) return std::unique_ptr(new Reply(rtsp::STATUS_NotAcceptable)); manager_->Play(); return std::unique_ptr(new Reply(rtsp::STATUS_OK)); } M16Sender::M16Sender(const InitParams& init_params) : OptionalMessageSender(init_params) { } bool M16Sender::HandleReply(Reply* reply) { return (reply->response_code() == rtsp::STATUS_OK); } SessionState::SessionState(const InitParams& init_params, unsigned& timer_id, MessageHandlerPtr& m16_sender) : MessageSequenceWithOptionalSetHandler(init_params) { AddSequencedHandler(make_ptr(new M5Handler(init_params))); AddSequencedHandler(make_ptr(new M6Handler(init_params, timer_id))); AddSequencedHandler(make_ptr(new M7Handler(init_params))); AddOptionalHandler(m16_sender); } SessionState::~SessionState() { } } // source } // wds ================================================ FILE: libwds/source/session_state.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_SOURCE_SESSION_STATE_H_ #define LIBWDS_SOURCE_SESSION_STATE_H_ #include "libwds/common/message_handler.h" namespace wds { namespace source { // WFD session state for RTSP source. // Includes M5, M6, M7 messages handling and optionally can handle M3, M4, M8 class SessionState : public MessageSequenceWithOptionalSetHandler { public: SessionState(const InitParams& init_params, unsigned& timer_id, MessageHandlerPtr& m16_sender); ~SessionState() override; }; class M7Handler final : public MessageReceiver { public: M7Handler(const InitParams& init_params); private: std::unique_ptr HandleMessage( rtsp::Message* message) override; }; class M16Sender final : public OptionalMessageSender { public: M16Sender(const InitParams& init_params); private: bool HandleReply(rtsp::Reply* reply) override; }; } // source } // wds #endif // LIBWDS_SOURCE_SESSION_STATE_H_ ================================================ FILE: libwds/source/source.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/public/source.h" #include "libwds/source/cap_negotiation_state.h" #include "libwds/source/init_state.h" #include "libwds/source/streaming_state.h" #include "libwds/source/session_state.h" #include "libwds/common/message_handler.h" #include "libwds/common/rtsp_input_handler.h" #include "libwds/public/wds_export.h" #include "libwds/rtsp/getparameter.h" #include "libwds/rtsp/setparameter.h" #include "libwds/rtsp/triggermethod.h" #include "libwds/public/media_manager.h" namespace wds { using rtsp::Message; using rtsp::Request; using rtsp::Reply; namespace { bool InitializeRequestId(Request* request) { Request::ID id = Request::UNKNOWN; switch(request->method()) { case Request::MethodOptions: id = Request::M2; break; case Request::MethodSetup: id = Request::M6; break; case Request::MethodPlay: id = Request::M7; break; case Request::MethodTeardown: id = Request::M8; break; case Request::MethodPause: id = Request::M9; break; case Request::MethodSetParameter: if (auto payload = rtsp::ToPropertyMapPayload(request->payload())) { if (payload->HasProperty(rtsp::RoutePropertyType)) id = Request::M10; else if (payload->HasProperty(rtsp::ConnectorTypePropertyType)) id = Request::M11; else if (payload->HasProperty(rtsp::StandbyPropertyType)) id = Request::M12; else if (payload->HasProperty(rtsp::IDRRequestPropertyType)) id = Request::M13; else if (payload->HasProperty(rtsp::UIBCCapabilityPropertyType)) id = Request::M14; else if (payload->HasProperty(rtsp::UIBCSettingPropertyType)) id = Request::M15; break; } default: WDS_ERROR("Failed to identify the received message"); return false; } request->set_id(id); return true; } } class SourceStateMachine : public MessageSequenceHandler { public: SourceStateMachine(const InitParams& init_params, unsigned& timer_id) : MessageSequenceHandler(init_params) { MessageHandlerPtr m16_sender = make_ptr(new source::M16Sender(init_params)); AddSequencedHandler(make_ptr(new source::InitState(init_params))); AddSequencedHandler(make_ptr(new source::CapNegotiationState(init_params))); AddSequencedHandler(make_ptr(new source::SessionState(init_params, timer_id, m16_sender))); AddSequencedHandler(make_ptr(new source::StreamingState(init_params, m16_sender))); } }; class SourceImpl final : public Source, public RTSPInputHandler, public MessageHandler::Observer { public: SourceImpl(Delegate* delegate, SourceMediaManager* mng, Peer::Observer* observer); private: // Source implementation. void Start() override; void Reset() override; void RTSPDataReceived(const std::string& message) override; bool Teardown() override; bool Play() override; bool Pause() override; // public MessageHandler::Observer void OnCompleted(MessageHandlerPtr handler) override; void OnError(MessageHandlerPtr handler) override; void OnTimerEvent(unsigned timer_id) override; // RTSPInputHandler void MessageParsed(std::unique_ptr message) override; void ParserErrorOccurred(const std::string& invalid_input) override; // Keep-alive function void SendKeepAlive(); void ResetAndTeardownMedia(); unsigned keep_alive_timer_; std::shared_ptr state_machine_; Delegate* delegate_; SourceMediaManager* media_manager_; Peer::Observer* observer_; }; SourceImpl::SourceImpl(Delegate* delegate, SourceMediaManager* mng, Peer::Observer* observer) : keep_alive_timer_(0), state_machine_(new SourceStateMachine({delegate, mng, this}, keep_alive_timer_)), delegate_(delegate), media_manager_(mng), observer_(observer) { } void SourceImpl::Start() { state_machine_->Start(); } void SourceImpl::Reset() { state_machine_->Reset(); delegate_->ReleaseTimer(keep_alive_timer_); } void SourceImpl::RTSPDataReceived(const std::string& message) { AddInput(message); } void SourceImpl::OnTimerEvent(unsigned timer_id) { if (keep_alive_timer_ == timer_id) SendKeepAlive(); else if (state_machine_->HandleTimeoutEvent(timer_id) && observer_) observer_->ErrorOccurred(TimeoutError); } void SourceImpl::SendKeepAlive() { delegate_->ReleaseTimer(keep_alive_timer_); auto get_param = std::unique_ptr( new rtsp::GetParameter("rtsp://localhost/wfd1.0")); get_param->header().set_cseq(delegate_->GetNextCSeq()); get_param->set_id(Request::M16); assert(state_machine_->CanSend(get_param.get())); state_machine_->Send(std::move(get_param)); keep_alive_timer_ = delegate_->CreateTimer(kDefaultKeepAliveTimeout - kDefaultTimeoutValue); assert(keep_alive_timer_); } namespace { std::unique_ptr CreateM5(int send_cseq, rtsp::TriggerMethod::Method method) { auto set_param = std::unique_ptr( new rtsp::SetParameter("rtsp://localhost/wfd1.0")); set_param->header().set_cseq(send_cseq); auto payload = new rtsp::PropertyMapPayload(); payload->AddProperty( std::shared_ptr(new rtsp::TriggerMethod(method))); set_param->set_payload(std::unique_ptr(payload)); set_param->set_id(Request::M5); return std::move(set_param); } } bool SourceImpl::Teardown() { auto m5 = CreateM5(delegate_->GetNextCSeq(), rtsp::TriggerMethod::TEARDOWN); if (!state_machine_->CanSend(m5.get())) return false; state_machine_->Send(std::move(m5)); return true; } bool SourceImpl::Play() { auto m5 = CreateM5(delegate_->GetNextCSeq(), rtsp::TriggerMethod::PLAY); if (!state_machine_->CanSend(m5.get())) return false; state_machine_->Send(std::move(m5)); return true; } bool SourceImpl::Pause() { auto m5 = CreateM5(delegate_->GetNextCSeq(), rtsp::TriggerMethod::PAUSE); if (!state_machine_->CanSend(m5.get())) return false; state_machine_->Send(std::move(m5)); return true; } void SourceImpl::OnCompleted(MessageHandlerPtr handler) { assert(handler == state_machine_); if (observer_) observer_->SessionCompleted(); } void SourceImpl::OnError(MessageHandlerPtr handler) { assert(handler == state_machine_); if (observer_) observer_->ErrorOccurred(UnexpectedMessageError); } void SourceImpl::MessageParsed(std::unique_ptr message) { if (message->is_request() && !InitializeRequestId(ToRequest(message.get()))) { WDS_ERROR("Cannot identify the received message"); if (observer_) observer_->ErrorOccurred(UnexpectedMessageError); return; } if (!state_machine_->CanHandle(message.get())) { WDS_ERROR("Cannot handle the received message with Id: %d", ToRequest(message.get())->id()); if (observer_) observer_->ErrorOccurred(UnexpectedMessageError); return; } state_machine_->Handle(std::move(message)); } void SourceImpl::ParserErrorOccurred(const std::string& invalid_input) { WDS_ERROR("Failed to parse: %s", invalid_input.c_str()); if (observer_) observer_->ErrorOccurred(MessageParseError); } Source* Source::Create(Delegate* delegate, SourceMediaManager* mng, Peer::Observer* observer) { return new SourceImpl(delegate, mng, observer); } } // namespace wds ================================================ FILE: libwds/source/streaming_state.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "libwds/source/streaming_state.h" #include "libwds/public/media_manager.h" #include "libwds/source/cap_negotiation_state.h" #include "libwds/source/session_state.h" #include "libwds/rtsp/reply.h" namespace wds { using rtsp::Message; using rtsp::Request; using rtsp::Reply; namespace source { class M8Handler final : public MessageReceiver { public: M8Handler(const InitParams& init_params) : MessageReceiver(init_params) { } private: std::unique_ptr HandleMessage( rtsp::Message* message) override { manager_->Teardown(); return std::unique_ptr(new Reply(rtsp::STATUS_OK)); } }; class M9Handler final : public MessageReceiver { public: M9Handler(const InitParams& init_params) : MessageReceiver(init_params) { } std::unique_ptr HandleMessage( Message* message) override { int response_code = rtsp::STATUS_NotAcceptable; if (!manager_->IsPaused()) { manager_->Pause(); response_code = rtsp::STATUS_OK; } return std::unique_ptr(new Reply(response_code)); } }; class M5Sender final : public OptionalMessageSender { public: M5Sender(const InitParams& init_params) : OptionalMessageSender(init_params) { } bool HandleReply(Reply* reply) override { return (reply->response_code() == rtsp::STATUS_OK); } }; class M13Handler final : public MessageReceiver { public: M13Handler(const InitParams& init_params) : MessageReceiver(init_params) { } std::unique_ptr HandleMessage( Message* message) override { ToSourceMediaManager(manager_)->SendIDRPicture(); return std::unique_ptr(new Reply(rtsp::STATUS_OK)); } }; StreamingState::StreamingState(const InitParams& init_params, MessageHandlerPtr m16_sender) : MessageSequenceWithOptionalSetHandler(init_params) { AddSequencedHandler(make_ptr(new M8Handler(init_params))); AddOptionalHandler(make_ptr(new M5Sender(init_params))); AddOptionalHandler(make_ptr(new M7Handler(init_params))); AddOptionalHandler(make_ptr(new M9Handler(init_params))); AddOptionalHandler(make_ptr(new M13Handler(init_params))); AddOptionalHandler(m16_sender); } StreamingState::~StreamingState() { } } // source } // wds ================================================ FILE: libwds/source/streaming_state.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBWDS_SOURCE_STREAMING_STATE_H_ #define LIBWDS_SOURCE_STREAMING_STATE_H_ #include "libwds/common/message_handler.h" namespace wds { namespace source { // Streaming state for RTSP source. // Includes M8 message handling and optionally can handle M3, M4, M7, M9-M15 class StreamingState : public MessageSequenceWithOptionalSetHandler { public: StreamingState(const InitParams& init_params, MessageHandlerPtr m16_sender); ~StreamingState() override; }; } // source } // wds #endif // LIBWDS_SOURCE_STREAMING_STATE_H_ ================================================ FILE: mirac_network/CMakeLists.txt ================================================ #FIXME in the future: with cmake 2.8.12 and up it's better #to use target_compile_options or add_compile_options set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pthread -std=c++11") include_directories ("${PROJECT_SOURCE_DIR}" ) include_directories ("${PROJECT_SOURCE_DIR}/include" ) include_directories ("${PROJECT_SOURCE_DIR}/libwds/rtsp" ) include_directories ("${PROJECT_SOURCE_DIR}/libwds/public" ) find_package(PkgConfig REQUIRED) pkg_check_modules (GLIB2 REQUIRED glib-2.0) include_directories(${GLIB2_INCLUDE_DIRS}) pkg_check_modules (GIO REQUIRED gio-2.0) include_directories(${GIO_INCLUDE_DIRS}) pkg_check_modules (GST REQUIRED gstreamer-1.0) include_directories(${GST_INCLUDE_DIRS}) add_library(mirac STATIC mirac-network.cpp mirac-gst-sink.cpp mirac-gst-test-source.cpp mirac-broker.cpp mirac-glib-logging.cpp mirac-gst-bus-handler.cpp) add_executable(network-test network-test.cpp) target_link_libraries (network-test ${GLIB2_LIBRARIES} mirac) add_executable(gst-test gst-test.cpp) target_link_libraries (gst-test mirac wds ${GLIB2_LIBRARIES} ${GIO_LIBRARIES} ${GST_LIBRARIES}) if (WDS_INSTALL_TESTS) install(PROGRAMS network-test gst-test DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}) endif() ================================================ FILE: mirac_network/gst-test.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * Contact: Alexander Kanavin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include "mirac-gst-test-source.hpp" #include "mirac-gst-sink.hpp" #include "mirac-glib-logging.hpp" static gboolean _sig_handler (gpointer data_ptr) { GMainLoop *ml = (GMainLoop *) data_ptr; g_main_loop_quit(ml); return G_SOURCE_CONTINUE; } int main (int argc, char *argv[]) { InitGlibLogging(); GError *error = NULL; GOptionContext *context; GMainLoop* ml = NULL; gchar* wfd_device_option = NULL; gchar* wfd_stream_option = NULL; gchar* hostname_option = NULL; gint port = 0; GOptionEntry main_entries[] = { { "device", 0, 0, G_OPTION_ARG_STRING, &wfd_device_option, "Specify WFD device type: testsource or sink", "(testsource|sink)"}, { "stream", 0, 0, G_OPTION_ARG_STRING, &wfd_stream_option, "Specify WFD stream type for testsource: audio, video, both or desktop capture", "(audio|video|both|desktop)"}, { "hostname", 0, 0, G_OPTION_ARG_STRING, &hostname_option, "Specify optional hostname or ip address to stream to or listen on", "host"}, { "port", 0, 0, G_OPTION_ARG_INT, &port, "Specify optional UDP port number to stream to or listen on", "port"}, { NULL } }; context = g_option_context_new ("- WFD source/sink demo application\n\nExample:\ngst-test --device=testsource --stream=both --hostname=127.0.0.1 --port=5000\ngst-test --device=sink --port=5000"); g_option_context_add_main_entries (context, main_entries, NULL); if (!g_option_context_parse (context, &argc, &argv, &error)) { WDS_ERROR ("option parsing failed: %s", error->message); g_option_context_free(context); exit (1); } g_option_context_free(context); wfd_test_stream_t wfd_stream = WFD_UNKNOWN_STREAM; if (g_strcmp0(wfd_stream_option, "audio") == 0) wfd_stream = WFD_TEST_AUDIO; else if (g_strcmp0(wfd_stream_option, "video") == 0) wfd_stream = WFD_TEST_VIDEO; else if (g_strcmp0(wfd_stream_option, "both") == 0) wfd_stream = WFD_TEST_BOTH; else if (g_strcmp0(wfd_stream_option, "desktop") == 0) wfd_stream = WFD_DESKTOP; std::string hostname; if (hostname_option) hostname = hostname_option; g_free(wfd_stream_option); g_free(hostname_option); gst_init (&argc, &argv); std::unique_ptr sink_pipeline; std::unique_ptr source_pipeline; if (g_strcmp0(wfd_device_option, "testsource") == 0) { source_pipeline.reset(new MiracGstTestSource(wfd_stream, hostname, port)); source_pipeline->SetState(GST_STATE_PLAYING); WDS_LOG("Source UDP port: %d", source_pipeline->UdpSourcePort()); } else if (g_strcmp0(wfd_device_option, "sink") == 0) { sink_pipeline.reset(new MiracGstSink(hostname, port)); WDS_LOG("Listening on port %d", sink_pipeline->sink_udp_port()); } g_free(wfd_device_option); ml = g_main_loop_new(NULL, TRUE); g_unix_signal_add(SIGINT, _sig_handler, ml); g_unix_signal_add(SIGTERM, _sig_handler, ml); g_main_loop_run(ml); g_main_loop_unref(ml); return 0; } ================================================ FILE: mirac_network/mirac-broker.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include "mirac-broker.hpp" #include "mirac-glib-logging.hpp" struct TimerCallbackData { TimerCallbackData(MiracBroker* delegate) : delegate_(delegate), timer_id_(0) {} MiracBroker* delegate_; uint timer_id_; }; /* static C callback wrapper */ gboolean MiracBroker::send_cb (gint fd, GIOCondition condition, gpointer data_ptr) { auto broker = static_cast (data_ptr); return (*broker)->send_cb(fd, condition); } /* static C callback wrapper */ gboolean MiracBroker::receive_cb (gint fd, GIOCondition condition, gpointer data_ptr) { auto broker = static_cast (data_ptr); return (*broker)->receive_cb(fd, condition); } /* static C callback wrapper */ gboolean MiracBroker::listen_cb (gint fd, GIOCondition condition, gpointer data_ptr) { auto broker = static_cast (data_ptr); return (*broker)->listen_cb(fd, condition); } /* static C callback wrapper */ gboolean MiracBroker::connect_cb (gint fd, GIOCondition condition, gpointer data_ptr) { auto broker = static_cast (data_ptr); return (*broker)->connect_cb(fd, condition); } /* static C callback wrapper */ gboolean MiracBroker::try_connect (gpointer data_ptr) { auto broker = static_cast (data_ptr); broker->try_connect(); return false; } gboolean MiracBroker::send_cb (gint fd, GIOCondition condition) { try { if (!connection_->Send()) return G_SOURCE_CONTINUE; } catch (const MiracConnectionLostException &exception) { on_connection_failure(CONNECTION_LOST); } catch (const std::exception &x) { WDS_WARNING("exception: %s", x.what()); } return G_SOURCE_REMOVE; } gboolean MiracBroker::receive_cb (gint fd, GIOCondition condition) { std::string msg; try { if (connection_->Receive(msg)) { WDS_VLOG("Received RTSP message:\n%s", msg.c_str()); got_message (msg); } } catch (const MiracConnectionLostException &exception) { on_connection_failure(CONNECTION_LOST); return G_SOURCE_REMOVE; } return G_SOURCE_CONTINUE; } gboolean MiracBroker::listen_cb (gint fd, GIOCondition condition) { try { connection(network_->Accept()); WDS_LOG("connection from: %s", connection_->GetPeerAddress().c_str()); on_connected(); } catch (const std::exception &x) { WDS_WARNING("exception: %s", x.what()); } return G_SOURCE_CONTINUE; } gboolean MiracBroker::connect_cb (gint fd, GIOCondition condition) { try { if (!network_->Connect(NULL, NULL)) return G_SOURCE_CONTINUE; WDS_LOG("connection success to: %s", network_->GetPeerAddress().c_str()); connection(network_.release()); /* make sure any network event sources are removed */ network(NULL); on_connected(); } catch (const std::exception &x) { gdouble elapsed = 1000 * g_timer_elapsed(connect_timer_, NULL); if (elapsed + connect_wait_ > connect_timeout_) { on_connection_failure(CONNECTION_TIMEOUT); } else { connect_wait_id_ = g_timeout_add (connect_wait_, try_connect, this); } } return G_SOURCE_REMOVE; } void MiracBroker::network(MiracNetwork *connection) { while (g_source_remove_by_user_data(&network_source_ptr_)) ; network_.reset(connection); } void MiracBroker::connection(MiracNetwork *connection) { while (g_source_remove_by_user_data(&connection_source_ptr_)) ; connection_.reset(connection); if (connection_) g_unix_fd_add(connection_->GetHandle(), G_IO_IN, receive_cb, &connection_source_ptr_); } void MiracBroker::try_connect() { WDS_LOG("Trying to connect..."); connect_wait_id_ = 0; network(new MiracNetwork()); if (network_->Connect(peer_address_.c_str(), peer_port_.c_str())) { g_unix_fd_add(network_->GetHandle(), G_IO_OUT, MiracBroker::send_cb, &network_source_ptr_); } else { g_unix_fd_add(network_->GetHandle(), G_IO_OUT, MiracBroker::connect_cb, &network_source_ptr_); } } unsigned short MiracBroker::get_host_port() const { return network_->GetHostPort(); } std::string MiracBroker::get_peer_address() const { return connection_->GetPeerAddress(); } MiracBroker::MiracBroker (const std::string& listen_port): connect_timer_(NULL) { network_source_ptr_ = this; connection_source_ptr_ = this; network(new MiracNetwork()); network_->Bind(NULL, listen_port.c_str()); g_unix_fd_add(network_->GetHandle(), G_IO_IN, MiracBroker::listen_cb, &network_source_ptr_); } MiracBroker::MiracBroker(const std::string& peer_address, const std::string& peer_port, uint timeout): peer_address_(peer_address), peer_port_(peer_port), connect_timeout_(timeout) { network_source_ptr_ = this; connection_source_ptr_ = this; connect_timer_ = g_timer_new(); try_connect(); } MiracBroker::~MiracBroker () { network(NULL); connection(NULL); if (connect_timer_) { g_timer_destroy(connect_timer_); connect_timer_ = NULL; } if (connect_wait_id_ > 0) { g_source_remove(connect_wait_id_); connect_wait_id_ = 0; } while (!timers_.empty()) g_source_remove(timers_.front()); } void MiracBroker::SendRTSPData(const std::string& data) { WDS_VLOG("Sending RTSP message:\n%s", data.c_str()); if (connection_ && !connection_->Send(data)) g_unix_fd_add(connection_->GetHandle(), G_IO_OUT, send_cb, &connection_source_ptr_); } std::string MiracBroker::GetLocalIPAddress() const { return "127.0.0.1"; // FIXME : return the actual local IP address. } void MiracBroker::on_timeout_remove(gpointer user_data) { TimerCallbackData* data = static_cast(user_data); auto& timers = data->delegate_->timers_; auto it = std::find(timers.begin(), timers.end(), data->timer_id_); if (it != timers.end()) timers.erase(it); delete data; } static gboolean on_timeout(gpointer user_data) { TimerCallbackData* data = static_cast(user_data); data->delegate_->OnTimeout(data->timer_id_); return FALSE; } void MiracBroker::OnTimeout(uint timer_id) { Peer()->OnTimerEvent(timer_id); } uint MiracBroker::CreateTimer(int seconds) { TimerCallbackData* data = new TimerCallbackData(this); uint timer_id = g_timeout_add_seconds_full( G_PRIORITY_DEFAULT, seconds, on_timeout, data, on_timeout_remove); if (timer_id > 0) { data->timer_id_ = timer_id; timers_.push_back(timer_id); } else { delete data; } return timer_id; } void MiracBroker::ReleaseTimer(uint timer_id) { if (timer_id > 0) { auto it = std::find(timers_.begin(), timers_.end(), timer_id); if (it != timers_.end() ) g_source_remove(*it); } } int MiracBroker::GetNextCSeq(int* initial_peer_cseq) const { static int send_cseq_; ++send_cseq_; if (initial_peer_cseq && send_cseq_ == *initial_peer_cseq) send_cseq_ *= 2; return send_cseq_; } ================================================ FILE: mirac_network/mirac-broker.hpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef MIRAC_BROKER_HPP #define MIRAC_BROKER_HPP #include #include #include #include #include "libwds/public/peer.h" #include "mirac-network.hpp" class MiracBroker : public wds::Peer::Delegate { public: MiracBroker (const std::string& listen_port); MiracBroker(const std::string& peer_address, const std::string& peer_port, uint timeout = 3000); virtual ~MiracBroker (); unsigned short get_host_port() const; std::string get_peer_address() const; virtual wds::Peer* Peer() const = 0; void OnTimeout(uint timer_id); protected: enum ConnectionFailure { CONNECTION_TIMEOUT, CONNECTION_LOST, }; // wds::Peer::Delegate void SendRTSPData(const std::string& data) override; std::string GetLocalIPAddress() const override; uint CreateTimer(int seconds) override; void ReleaseTimer(uint timer_id) override; int GetNextCSeq(int* initial_peer_cseq = nullptr) const override; virtual void got_message(const std::string& data) {} virtual void on_connected() {}; virtual void on_connection_failure(ConnectionFailure failure) {}; private: static gboolean send_cb (gint fd, GIOCondition condition, gpointer data_ptr); static gboolean receive_cb (gint fd, GIOCondition condition, gpointer data_ptr); static gboolean listen_cb (gint fd, GIOCondition condition, gpointer data_ptr); static gboolean connect_cb (gint fd, GIOCondition condition, gpointer data_ptr); static gboolean try_connect(gpointer data_ptr); static void on_timeout_remove(gpointer user_data); gboolean send_cb (gint fd, GIOCondition condition); gboolean receive_cb (gint fd, GIOCondition condition); gboolean listen_cb (gint fd, GIOCondition condition); gboolean connect_cb (gint fd, GIOCondition condition); void try_connect(); void handle_body(const std::string msg); void handle_header(const std::string msg); void network(MiracNetwork* connection); std::unique_ptr network_; MiracBroker *network_source_ptr_; void connection(MiracNetwork* connection); std::unique_ptr connection_; MiracBroker *connection_source_ptr_; std::vector timers_; std::string peer_address_; std::string peer_port_; GTimer *connect_timer_; uint connect_wait_id_; uint connect_timeout_; static const uint connect_wait_ = 200; }; #endif /* MIRAC_BROKER_HPP */ ================================================ FILE: mirac_network/mirac-exception.hpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * Contact: Jussi Laako * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef MIRAC_EXCEPTION_HPP #define MIRAC_EXCEPTION_HPP #include #include class MiracException : public std::exception { public: MiracException () throw () { } MiracException (int error_code, const char *function = NULL) throw () { ec = error_code; msg = strerror(ec); add_func(function); } MiracException (const char *error_msg, const char *function = NULL) throw () { msg = error_msg; add_func(function); } MiracException (int error_code, const char *error_msg, const char *function = NULL) throw () { ec = error_code; msg = std::string(error_msg) + std::string(": ") + std::string(strerror(ec)); add_func(function); } virtual ~MiracException () throw () { } virtual const char * what () const throw () { return msg.c_str(); } virtual operator int () const throw () { return ec; } virtual operator std::string () const throw () { return msg; } protected: int ec; std::string msg; void add_func (const char *function) throw () { if (function) msg = std::string(function) + std::string("(): ") + msg; } }; #endif // MIRAC_EXCEPTION_HPP ================================================ FILE: mirac_network/mirac-glib-logging.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "mirac-glib-logging.hpp" #include namespace { void MiracGlibLog(const char* format, ...) { va_list va; va_start(va, format); g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, format, va); va_end(va); } void MiracGlibVLog(const char* format, ...) { va_list va; va_start(va, format); g_logv("rtsp", G_LOG_LEVEL_DEBUG, format, va); va_end(va); } void MiracGlibWarning(const char* format, ...) { va_list va; va_start(va, format); g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, format, va); va_end(va); } void MiracGlibError(const char* format, ...) { va_list va; va_start(va, format); g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, format, va); va_end(va); } } // namespace void InitGlibLogging() { wds::LogSystem::set_log_func(&MiracGlibLog); wds::LogSystem::set_vlog_func(&MiracGlibVLog); wds::LogSystem::set_warning_func(&MiracGlibWarning); wds::LogSystem::set_error_func(&MiracGlibError); } ================================================ FILE: mirac_network/mirac-glib-logging.hpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef MIRAC_LOGGING_HPP #define MIRAC_LOGGING_HPP #include "libwds/public/logging.h" void InitGlibLogging(); #endif // MIRAC_LOGGING_HPP ================================================ FILE: mirac_network/mirac-gst-bus-handler.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include "libwds/public/logging.h" gboolean mirac_gstbus_callback (GstBus *bus, GstMessage *message, gpointer data) { GError *err = NULL; gchar *debug = NULL; switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: gst_message_parse_error (message, &err, &debug); WDS_VLOG (debug); WDS_ERROR ("[%s] %s", g_quark_to_string(err->domain), err->message); g_error_free (err); g_free (debug); break; case GST_MESSAGE_WARNING: gst_message_parse_warning (message, &err, &debug); WDS_VLOG (debug); WDS_WARNING ("[%s] %s", g_quark_to_string(err->domain), err->message); g_error_free (err); g_free (debug); break; case GST_MESSAGE_INFO: gst_message_parse_info (message, &err, &debug); WDS_VLOG (debug); WDS_LOG ("[%s] %s", g_quark_to_string(err->domain), err->message); g_error_free (err); g_free (debug); break; default: /* unhandled message */ break; } return TRUE; } ================================================ FILE: mirac_network/mirac-gst-bus-handler.hpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2015 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef MIRAC_GST_BUS_HANDLER_HPP #define MIRAC_GST_BUS_HANDLER_HPP gboolean mirac_gstbus_callback (GstBus *bus, GstMessage *message, gpointer data); #endif ================================================ FILE: mirac_network/mirac-gst-sink.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "mirac-gst-sink.hpp" #include "mirac-gst-bus-handler.hpp" #include "libwds/public/logging.h" #include void _set_udp_caps(GstElement *playbin, GstElement *source, gpointer user_data) { GstCaps* caps = gst_caps_new_simple ("application/x-rtp", "media", G_TYPE_STRING, "video", "clock-rate", G_TYPE_INT, 1, "encoding-name", G_TYPE_STRING, "MP2T", NULL); g_object_set(source, "caps", caps, NULL); gst_caps_unref(caps); } MiracGstSink::MiracGstSink (std::string hostname, int port) { // todo (shalamov): move out pipeline initialization // from constructor, otherwise we can't check error conditions std::string gst_pipeline; std::string url = "udp://" + (!hostname.empty() ? hostname : "::") + (port > 0 ? ":" + std::to_string(port) : ":"); gst_pipeline = "playbin uri=" + url; GError *err = NULL; gst_elem = gst_parse_launch(gst_pipeline.c_str(), &err); if (err != NULL) { WDS_ERROR("Cannot initialize gstreamer pipeline: [%s] %s", g_quark_to_string(err->domain), err->message); } if (gst_elem) { GstBus* bus = gst_pipeline_get_bus (GST_PIPELINE (gst_elem)); bus_watch_id = gst_bus_add_watch (bus, mirac_gstbus_callback, this); gst_object_unref (bus); g_signal_connect(gst_elem, "source-setup", G_CALLBACK(_set_udp_caps), NULL); gst_element_set_state (gst_elem, GST_STATE_PLAYING); } } int MiracGstSink::sink_udp_port() { if (gst_elem == NULL) return 0; GstElement* source = NULL; g_object_get(gst_elem, "source", &source, NULL); if (source == NULL) return 0; gint port = 0; g_object_get(source, "port", &port, NULL); return port; } void MiracGstSink::Play() { assert(gst_elem); if(!IsInState(GST_STATE_PLAYING)) { gst_element_set_state(gst_elem, GST_STATE_PLAYING); IsInState(GST_STATE_PLAYING); } } void MiracGstSink::Pause() { assert(gst_elem); if(!IsPaused()) { gst_element_set_state(gst_elem, GST_STATE_PAUSED); IsPaused(); } } void MiracGstSink::Teardown() { assert(gst_elem); if(!IsInState(GST_STATE_READY)) { gst_element_set_state(gst_elem, GST_STATE_READY); IsInState(GST_STATE_READY); } } bool MiracGstSink::IsPaused() const { return IsInState(GST_STATE_PAUSED); } bool MiracGstSink::IsInState(GstState state) const { assert(gst_elem); GstState current_state; gst_element_get_state(gst_elem, ¤t_state, NULL, GST_CLOCK_TIME_NONE); return current_state == state; } MiracGstSink::~MiracGstSink () { if (gst_elem) { gst_element_set_state (gst_elem, GST_STATE_NULL); g_source_remove (bus_watch_id); gst_object_unref (GST_OBJECT (gst_elem)); } } ================================================ FILE: mirac_network/mirac-gst-sink.hpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef MIRAC_GST_SINK_HPP #define MIRAC_GST_SINK_HPP #include #include class MiracGstSink { public: MiracGstSink(std::string hostname, int port); ~MiracGstSink (); void Play(); void Pause(); bool IsPaused() const; void Teardown(); int sink_udp_port(); private: bool IsInState(GstState state) const; GstElement* gst_elem; guint bus_watch_id; }; #endif ================================================ FILE: mirac_network/mirac-gst-test-source.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * Contact: Alexander Kanavin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include "mirac-gst-test-source.hpp" #include "mirac-gst-bus-handler.hpp" #include "libwds/public/logging.h" MiracGstTestSource::MiracGstTestSource (wfd_test_stream_t wfd_stream_type, std::string hostname, int port) { std::string gst_pipeline; std::string hostname_port = (!hostname.empty() ? "host=" + hostname + " ": " ") + (port > 0 ? "port=" + std::to_string(port) : ""); if (wfd_stream_type == WFD_TEST_BOTH) { gst_pipeline = "videotestsrc ! videoconvert ! video/x-raw,format=I420 ! x264enc ! muxer. audiotestsrc ! avenc_ac3 ! muxer. mpegtsmux name=muxer ! rtpmp2tpay ! udpsink name=sink " + hostname_port; } else if (wfd_stream_type == WFD_TEST_AUDIO) { gst_pipeline = "audiotestsrc ! avenc_ac3 ! mpegtsmux ! rtpmp2tpay ! udpsink name=sink " + hostname_port; } else if (wfd_stream_type == WFD_TEST_VIDEO) { gst_pipeline = "videotestsrc ! videoconvert ! video/x-raw,format=I420 ! x264enc ! mpegtsmux ! rtpmp2tpay ! udpsink name=sink " + hostname_port; } else if (wfd_stream_type == WFD_DESKTOP) { gst_pipeline = "ximagesrc ! videoconvert ! video/x-raw,format=I420 ! x264enc tune=zerolatency ! mpegtsmux ! rtpmp2tpay ! udpsink name=sink " + hostname_port; } GError *err = NULL; gst_elem = gst_parse_launch(gst_pipeline.c_str(), &err); if (err != NULL) { WDS_ERROR("Cannot initialize gstreamer pipeline: [%s] %s", g_quark_to_string(err->domain), err->message); } if (gst_elem) { GstBus* bus = gst_pipeline_get_bus (GST_PIPELINE (gst_elem)); bus_watch_id = gst_bus_add_watch (bus, mirac_gstbus_callback, this); gst_object_unref (bus); } } void MiracGstTestSource::SetState(GstState state) { if (gst_elem) { gst_element_set_state (gst_elem, state); } } GstState MiracGstTestSource::GetState() const { if (!gst_elem) return GST_STATE_NULL; GstState result; gst_element_get_state (gst_elem, &result, NULL, GST_CLOCK_TIME_NONE); return result; } int MiracGstTestSource::UdpSourcePort() { if (gst_elem == NULL) return 0; GstElement* sink = NULL; sink = gst_bin_get_by_name(GST_BIN(gst_elem), "sink"); if (sink == NULL) return 0; GSocket* socket = NULL; g_object_get(sink, "used-socket", &socket, NULL); if (socket == NULL) return 0; guint16 port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(g_socket_get_local_address(socket, NULL))); return port; } MiracGstTestSource::~MiracGstTestSource () { if (gst_elem) { gst_element_set_state (gst_elem, GST_STATE_NULL); g_source_remove (bus_watch_id); gst_object_unref (GST_OBJECT (gst_elem)); } } ================================================ FILE: mirac_network/mirac-gst-test-source.hpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * Contact: Alexander Kanavin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef MIRAC_GST_TEST_SOURCE_HPP #define MIRAC_GST_TEST_SOURCE_HPP #include enum wfd_test_stream_t {WFD_TEST_AUDIO, WFD_TEST_VIDEO, WFD_TEST_BOTH, WFD_DESKTOP, WFD_UNKNOWN_STREAM}; class MiracGstTestSource { public: MiracGstTestSource(wfd_test_stream_t wfd_stream, std::string hostname, int port); ~MiracGstTestSource (); void SetState(GstState state); GstState GetState() const; int UdpSourcePort(); private: GstElement* gst_elem; guint bus_watch_id; }; #endif ================================================ FILE: mirac_network/mirac-network.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * Contact: Jussi Laako * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mirac-network.hpp" #define MIRAC_MAX_NAMELEN 255 MiracNetwork::MiracNetwork () { Init(); } MiracNetwork::MiracNetwork (int conn_handle) { Init(); handle = conn_handle; } MiracNetwork::~MiracNetwork () { Close(); } void MiracNetwork::Init () { long ps; handle = -1; ps = sysconf(_SC_PAGESIZE); page_size = (ps <= 0) ? 4096 : static_cast (ps); conn_ares = NULL; } void MiracNetwork::Close () { if (handle >= 0) close(handle); handle = -1; if (conn_ares) { freeaddrinfo(reinterpret_cast (conn_ares)); conn_ares = NULL; } } void MiracNetwork::Bind (const char *address, const char *service) { int ec; int reuse = 1; struct addrinfo *addr_res = NULL; struct addrinfo *bind_addr; struct addrinfo addr_hint; Close(); memset(&addr_hint, 0x00, sizeof(addr_hint)); addr_hint.ai_flags = AI_PASSIVE; ec = getaddrinfo(address, service, &addr_hint, &addr_res); if (ec) throw MiracException(gai_strerror(ec), __FUNCTION__); bind_addr = addr_res; while (bind_addr) { /* note, the SOCK_NONBLOCK is specific to Linux 2.6.27+, * on other platforms use either fcntl() or ioctl(h, FIONBIO, 1) */ handle = socket(addr_res->ai_family, addr_res->ai_socktype | SOCK_NONBLOCK, addr_res->ai_protocol); if (handle < 0) throw MiracException(errno, "socket()", __FUNCTION__); if (setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) throw MiracException(errno, "setsockopt()", __FUNCTION__); if (bind(handle, bind_addr->ai_addr, bind_addr->ai_addrlen) == 0) break; else if (!bind_addr->ai_next) throw MiracException(errno, "bind()", __FUNCTION__); close(handle); bind_addr = bind_addr->ai_next; } freeaddrinfo(addr_res); if (listen(handle, 1)) throw MiracException(errno, "listen()", __FUNCTION__); } MiracNetwork * MiracNetwork::Accept () { int ch; int nonblock = 1; ch = accept(handle, NULL, NULL); if (ch < 0) throw MiracException(errno, "accept()", __FUNCTION__); if (ioctl(ch, FIONBIO, &nonblock)) throw MiracException(errno, "ioctl(FIONBIO)", __FUNCTION__); return new MiracNetwork(ch); } bool MiracNetwork::Connect (const char *address, const char *service) { int ec = 0; if (address && service) { Close(); struct addrinfo addr_hint; memset(&addr_hint, 0x00, sizeof(addr_hint)); addr_hint.ai_socktype = SOCK_STREAM; ec = getaddrinfo(address, service, &addr_hint, reinterpret_cast (&conn_ares)); if (ec) throw MiracException(gai_strerror(ec), __FUNCTION__); conn_aptr = conn_ares; } else { socklen_t optlen = sizeof(ec); if (getsockopt(handle, SOL_SOCKET, SO_ERROR, &ec, &optlen)) throw MiracException(errno, "getsockopt()", __FUNCTION__); if (!ec) return true; conn_aptr = reinterpret_cast (conn_aptr)->ai_next; } struct addrinfo *addr = reinterpret_cast (conn_aptr); if (!addr) throw MiracException("peer unavailable", __FUNCTION__); /* note, the SOCK_NONBLOCK is specific to Linux 2.6.27+, * on other platforms use either fcntl() or ioctl(h, FIONBIO, 1) */ handle = socket(addr->ai_family, addr->ai_socktype | SOCK_NONBLOCK, addr->ai_protocol); if (handle < 0) throw MiracException(errno, "socket()", __FUNCTION__); if (connect(handle, addr->ai_addr, addr->ai_addrlen)) { if (errno == EINPROGRESS) return false; throw MiracException(errno, "connect()", __FUNCTION__); } return true; } std::string MiracNetwork::GetPeerAddress () { int ec; socklen_t addrsize = std::max(sizeof(sockaddr_in), sizeof(sockaddr_in6)); std::unique_ptr addrbuf(new uint8_t[addrsize]); std::unique_ptr namebuf(new char [MIRAC_MAX_NAMELEN + 1]); std::unique_ptr servbuf(new char [MIRAC_MAX_NAMELEN + 1]); if (getpeername(handle, reinterpret_cast (addrbuf.get()), &addrsize)) throw MiracException(errno, "getpeername()", __FUNCTION__); ec = getnameinfo( reinterpret_cast (addrbuf.get()), addrsize, namebuf.get(), MIRAC_MAX_NAMELEN, servbuf.get(), MIRAC_MAX_NAMELEN, NI_NOFQDN|NI_NUMERICHOST|NI_NUMERICSERV); if (ec) throw MiracException(gai_strerror(ec), __FUNCTION__); return std::string(namebuf.get()); } unsigned short MiracNetwork::GetHostPort () { socklen_t addrsize = std::max(sizeof(sockaddr_in), sizeof(sockaddr_in6)); std::unique_ptr addrbuf(new uint8_t[addrsize]); if (getsockname(handle, reinterpret_cast (addrbuf.get()), &addrsize)) throw MiracException(errno, "getsockname()", __FUNCTION__); struct sockaddr *saddr = reinterpret_cast (addrbuf.get()); if (saddr->sa_family == AF_INET) { struct sockaddr_in *ip4addr = reinterpret_cast (saddr); return ntohs(ip4addr->sin_port); } else if (saddr->sa_family == AF_INET6) { struct sockaddr_in6 *ip6addr = reinterpret_cast (saddr); return ntohs(ip6addr->sin6_port); } return 0; } bool MiracNetwork::Receive (std::string &message) { int ec; char nb[page_size]; do { ec = recv(handle, nb, page_size, 0); if (ec > 0) message.append(nb, ec); else if (ec < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) break; if (errno == ECONNRESET) throw MiracConnectionLostException( __FUNCTION__); throw MiracException(errno, "recv()", __FUNCTION__); } else // ec == 0 throw MiracConnectionLostException( __FUNCTION__); } while (ec > 0); return true; } bool MiracNetwork::Receive (std::string &message, size_t length) { int ec; char nb[page_size]; do { ec = recv(handle, nb, page_size, 0); if (ec > 0) recv_buf.append(nb, ec); else if (ec < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) break; if (errno == ECONNRESET) throw MiracConnectionLostException( __FUNCTION__); throw MiracException(errno, "recv()", __FUNCTION__); } else // ec == 0 throw MiracConnectionLostException( __FUNCTION__); } while (ec > 0); if (recv_buf.size() < length) return false; message = recv_buf.substr(0, length); recv_buf.erase(0, length); return true; } bool MiracNetwork::Send (const std::string &message) { int ec; if (!message.empty()) send_buf.append(message); do { ec = send(handle, send_buf.c_str(), send_buf.size(), MSG_NOSIGNAL); if (ec > 0) send_buf.erase(0, ec); else { if (errno == EAGAIN || errno == EWOULDBLOCK) return false; if (errno == EPIPE || errno == ENOTCONN) throw MiracConnectionLostException(__FUNCTION__); throw MiracException(errno, "send()", __FUNCTION__); } } while (send_buf.size() > 0); return true; } ================================================ FILE: mirac_network/mirac-network.hpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * Contact: Jussi Laako * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef MIRAC_NETWORK_HPP #define MIRAC_NETWORK_HPP #include #include #include "mirac-exception.hpp" class MiracConnectionLostException : public MiracException { public: MiracConnectionLostException (const char *function = NULL) throw () { msg = std::string("Connection lost"); add_func(function); } virtual ~MiracConnectionLostException () throw () { } }; class MiracNetwork { public: MiracNetwork (); MiracNetwork (int conn_handle); virtual ~MiracNetwork (); void Bind (const char *address, const char *service); MiracNetwork * Accept (); bool Connect (const char *address, const char *service); int GetHandle () const { return handle; } std::string GetPeerAddress (); unsigned short GetHostPort (); bool Receive (std::string &message); bool Receive (std::string &message, size_t length); bool Send (const std::string &message = std::string()); protected: int handle; size_t page_size; std::string recv_buf; std::string send_buf; void Init (); void Close (); private: void *conn_ares; void *conn_aptr; }; #endif /* MIRAC_NETWORK_HPP */ ================================================ FILE: mirac_network/network-test.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * Contact: Jussi Laako * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include "mirac-network.hpp" static gboolean _sig_handler (gpointer data_ptr) { GMainLoop *ml = (GMainLoop *) data_ptr; g_main_loop_quit(ml); return G_SOURCE_CONTINUE; } static gboolean _send_cb (gint fd, GIOCondition condition, gpointer data_ptr) { MiracNetwork *ctx = reinterpret_cast (data_ptr); try { return ctx->Send() ? G_SOURCE_REMOVE : G_SOURCE_CONTINUE; } catch (std::exception &x) { g_warning("exception: %s", x.what()); delete ctx; } return G_SOURCE_REMOVE; } static gboolean _receive_cb (gint fd, GIOCondition condition, gpointer data_ptr) { MiracNetwork *ctx = reinterpret_cast (data_ptr); try { std::string msg; if (ctx->Receive(msg)) { g_message("message: %s", msg.c_str()); if (!ctx->Send(msg)) g_unix_fd_add(ctx->GetHandle(), G_IO_OUT, _send_cb, ctx); } } catch (std::exception &x) { g_warning("exception: %s", x.what()); delete ctx; return G_SOURCE_REMOVE; } return G_SOURCE_CONTINUE; } static gboolean _listen_cb (gint fd, GIOCondition condition, gpointer data_ptr) { try { MiracNetwork *listener = reinterpret_cast (data_ptr); MiracNetwork *ctx; ctx = listener->Accept(); g_message("connection from: %s", ctx->GetPeerAddress().c_str()); g_unix_fd_add(ctx->GetHandle(), G_IO_IN, _receive_cb, ctx); } catch (std::exception &x) { g_warning("exception: %s", x.what()); } return G_SOURCE_CONTINUE; } static gboolean _sendmsg_cb (gint fd, GIOCondition condition, gpointer data_ptr) { try { MiracNetwork *ctx = reinterpret_cast (data_ptr); if (!ctx->Send (std::string("Hello world!\r\n\r\n"))) g_unix_fd_add(ctx->GetHandle(), G_IO_OUT, _send_cb, ctx); } catch (std::exception &x) { g_warning("exception %s", x.what()); } return G_SOURCE_REMOVE; } static gboolean _connect_cb (gint fd, GIOCondition condition, gpointer data_ptr) { try { MiracNetwork *ctx = reinterpret_cast (data_ptr); if (!ctx->Connect(NULL, NULL)) return G_SOURCE_CONTINUE; g_message("connection success to: %s", ctx->GetPeerAddress().c_str()); g_unix_fd_add(ctx->GetHandle(), G_IO_OUT, _sendmsg_cb, ctx); } catch (std::exception &x) { g_warning("exception: %s", x.what()); } return G_SOURCE_REMOVE; } int main (int argc, char *argv[]) { GMainLoop *ml = NULL; try { ml = g_main_loop_new(NULL, TRUE); g_unix_signal_add(SIGINT, _sig_handler, ml); g_unix_signal_add(SIGTERM, _sig_handler, ml); std::unique_ptr net_listen(new MiracNetwork); std::unique_ptr net_conn(new MiracNetwork); net_listen->Bind("127.0.0.1", "8080"); g_message("bound to port %hu", net_listen->GetHostPort()); g_unix_fd_add(net_listen->GetHandle(), G_IO_IN, _listen_cb, net_listen.get()); if (net_conn->Connect("127.0.0.1", "8080")) g_unix_fd_add(net_conn->GetHandle(), G_IO_OUT, _sendmsg_cb, net_conn.get()); else g_unix_fd_add(net_conn->GetHandle(), G_IO_OUT, _connect_cb, net_conn.get()); g_main_loop_run(ml); } catch (std::exception &x) { g_error("exception: %s", x.what()); } if (ml) g_main_loop_unref(ml); return 0; } ================================================ FILE: p2p/CMakeLists.txt ================================================ #FIXME in the future: with cmake 2.8.12 and up it's better #to use target_compile_options or add_compile_options set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -std=c++11 -ggdb3 -Wall") set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -O0 -std=c99 -ggdb3 -Wall") find_package(PkgConfig REQUIRED) pkg_check_modules (GIO REQUIRED gio-2.0) include_directories(${GIO_INCLUDE_DIRS}) add_library(p2p STATIC connman-peer.cpp connman-client.cpp information-element.cpp ) add_executable(register-peer-service main.cpp) target_link_libraries (register-peer-service p2p ${GIO_LIBRARIES}) add_executable(test-ie test-ie.cpp) target_link_libraries (test-ie p2p ${GIO_LIBRARIES}) add_test(InformationElementTest test-ie) if (WDS_INSTALL_TESTS) install(PROGRAMS test-ie DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}) endif() ================================================ FILE: p2p/connman-client.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include "connman-client.h" namespace P2P { void Client::connman_appeared_cb(GDBusConnection *connection, const char *name, const char *owner, gpointer data_ptr) { g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, "net.connman", "/", "net.connman.Manager", NULL, Client::proxy_cb, data_ptr); /* TODO should get the p2p object path * by watching Manager.TechnologyAdded/TechnologyRemoved */ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, "net.connman", "/net/connman/technology/p2p", "net.connman.Technology", NULL, Client::technology_proxy_cb, data_ptr); } void Client::connman_disappeared_cb(GDBusConnection *connection, const char *name, gpointer data_ptr) { auto client = static_cast (data_ptr); client->connman_disappeared (); } /* static C callback */ void Client::proxy_signal_cb (GDBusProxy *proxy, const char *sender, const char *signal, GVariant *params, gpointer data_ptr) { if (g_strcmp0(signal, "PeersChanged") != 0) return; auto client = static_cast (data_ptr); client->peers_changed (params); } void Client::get_technologies_cb (GObject *object, GAsyncResult *res, gpointer data_ptr) { GError *error = NULL; GDBusProxy *proxy = G_DBUS_PROXY (object); char *object_path; bool p2p_found = false; GVariant *params; GVariantIter *iter; params = g_dbus_proxy_call_finish (proxy, res, &error); if (error) { std::cout << "GetTechnologies error " << error->message << std::endl; g_clear_error (&error); } g_variant_get (params, "(a(oa{sv}))", &iter); while (g_variant_iter_loop (iter, "(oa{sv})", &object_path, NULL)) { /* TODO: warn if P2P is not enabled. Also, don't set * the client available before P2P is enabled */ if (g_strcmp0(object_path, "/net/connman/technology/p2p") == 0) { p2p_found = true; break; } } g_variant_unref(params); g_variant_iter_free (iter); if (!p2p_found) std::cout << "Warning: P2P not found in Connman technologies." << std::endl; } void Client::register_peer_service_cb (GObject *object, GAsyncResult *res, gpointer data_ptr) { GError *error = NULL; GDBusProxy *proxy = G_DBUS_PROXY (object); g_dbus_proxy_call_finish (proxy, res, &error); if (error) { std::cout << "register error " << error->message << std::endl; g_clear_error (&error); return; } } void Client::get_peers_cb (GObject *object, GAsyncResult *res, gpointer data_ptr) { GError *error = NULL; GDBusProxy *proxy = G_DBUS_PROXY(object); GVariantIter *peer_iter; GVariant *params; params = g_dbus_proxy_call_finish(proxy, res, &error); if (error) { std::cout << "GetPeers error " << error->message << std::endl; g_clear_error(&error); return; } g_variant_get(params, "(a(oa{sv}))", &peer_iter); auto client = static_cast(data_ptr); client->handle_new_peers(peer_iter); g_variant_unref(params); g_variant_iter_free(peer_iter); } /* static C callback */ void Client::scan_cb (GObject *object, GAsyncResult *res, gpointer data_ptr) { GError *error = NULL; GDBusProxy *proxy = G_DBUS_PROXY (object); g_dbus_proxy_call_finish (proxy, res, &error); if (error) { std::cout << "scan error " << error->message << std::endl; g_clear_error (&error); return; } std::cout << "* scan complete"<< std::endl; } /* static C callback */ void Client::proxy_cb (GObject *object, GAsyncResult *res, gpointer data_ptr) { auto client = static_cast (data_ptr); client->proxy_cb (res); } /* static C callback */ void Client::technology_proxy_cb (GObject *object, GAsyncResult *res, gpointer data_ptr) { auto client = static_cast (data_ptr); client->technology_proxy_cb (res); } void Client::connman_disappeared() { bool was_available = is_available(); if (proxy_) g_clear_object (&proxy_); if (technology_proxy_) g_clear_object (&technology_proxy_); if (observer_ && was_available) observer_->on_availability_changed(this); } void Client::handle_new_peers (GVariantIter *added) { GVariantIter *props; const char *path; while (g_variant_iter_loop(added, "(oa{sv})", &path, &props)) { try { peers_[path] = std::make_shared(path, props); if (observer_) observer_->on_peer_added(this, peers_[path]); } catch (std::invalid_argument &x) { /* Not a miracast peer */ } } } void Client::peers_changed (GVariant *params) { GVariantIter *added, *removed; const char *path; g_variant_get(params, "(a(oa{sv})ao)", &added, &removed); handle_new_peers(added); while (g_variant_iter_loop (removed, "o", &path)) { auto it = peers_.find(path); if (it == peers_.end()) return; if (observer_) observer_->on_peer_removed(this, it->second); peers_.erase(it); } g_variant_iter_free (added); g_variant_iter_free (removed); } void Client::register_peer_service () { GVariantBuilder builder; /* HACK: Connman should figure out the "master" boolean on its own but it does not. * We need to do it here with InformationElement for now... */ P2P::InformationElement ie(array_); bool is_master = (ie.get_device_type() != P2P::SOURCE); g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}")); g_variant_builder_add (&builder, "{sv}", "WiFiDisplayIEs", g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, array_->bytes, array_->length, 1)); g_dbus_proxy_call (proxy_, "RegisterPeerService", g_variant_new ("(a{sv}b)", &builder, is_master), G_DBUS_CALL_FLAGS_NONE, -1, NULL, Client::register_peer_service_cb, this); } void Client::unregister_peer_service () { GVariantBuilder builder; g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}")); g_variant_builder_add (&builder, "{sv}", "WiFiDisplayIEs", g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, array_->bytes, array_->length, 1)); g_dbus_proxy_call (proxy_, "UnregisterPeerService", g_variant_new ("(a{sv}b)", &builder, TRUE), G_DBUS_CALL_FLAGS_NONE, -1, NULL, Client::register_peer_service_cb, this); } void Client::initialize_peers () { g_dbus_proxy_call(proxy_, "GetPeers", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, Client::get_peers_cb, this); } void Client::proxy_cb (GAsyncResult *result) { GError *error = NULL; proxy_ = g_dbus_proxy_new_for_bus_finish(result, &error); if (error) { std::cout << "proxy error "<< std::endl; g_clear_error (&error); return; } g_signal_connect(proxy_, "g-signal", G_CALLBACK (Client::proxy_signal_cb), this); g_dbus_proxy_call(proxy_, "GetTechnologies", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, Client::get_technologies_cb, this); initialize_peers(); register_peer_service(); if(observer_ && is_available()) observer_->on_availability_changed(this); } void Client::technology_proxy_cb (GAsyncResult *result) { GError *error = NULL; technology_proxy_ = g_dbus_proxy_new_for_bus_finish(result, &error); if (error) { std::cout << "tech proxy error "<< std::endl; g_clear_error (&error); } if(observer_ && is_available()) observer_->on_availability_changed(this); } Client::Client(std::unique_ptr &take_array, Observer *observer): proxy_(NULL), technology_proxy_(NULL), observer_(observer), array_(std::move(take_array)) { connman_watcher_ = g_bus_watch_name (G_BUS_TYPE_SYSTEM, "net.connman", G_BUS_NAME_WATCHER_FLAGS_NONE, Client::connman_appeared_cb, Client::connman_disappeared_cb, this, NULL); } Client::~Client() { if (connman_watcher_ != 0) { g_bus_unwatch_name (connman_watcher_); connman_watcher_ = 0; } if (proxy_) g_clear_object (&proxy_); if (technology_proxy_) g_clear_object (&technology_proxy_); } void Client::set_information_element(std::unique_ptr &take_array) { g_return_if_fail (is_available()); unregister_peer_service(); array_ = std::move (take_array); register_peer_service(); } bool Client::is_available() const { return proxy_ && technology_proxy_; } void Client::scan() { g_return_if_fail (is_available()); g_dbus_proxy_call (technology_proxy_, "Scan", NULL, G_DBUS_CALL_FLAGS_NONE, 60 * 1000, NULL, Client::scan_cb, this); } } ================================================ FILE: p2p/connman-client.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef CONNMAN_CLIENT_H_ #define CONNMAN_CLIENT_H_ #include #include #include "information-element.h" #include "connman-peer.h" namespace P2P { class Client { public: class Observer { public: virtual void on_peer_added(Client *client, std::shared_ptr peer) {} virtual void on_peer_removed(Client *client, std::shared_ptr peer) {} virtual void on_availability_changed(Client *client) {} protected: virtual ~Observer() {} }; Client(std::unique_ptr &take_array, Observer *observer = NULL); virtual ~Client(); void set_information_element(std::unique_ptr &take_array); void set_observer(Observer* observer) { observer_ = observer; } bool is_available() const; /* TODO error / finished handling */ void scan(); private: static void connman_appeared_cb(GDBusConnection *connection, const char *name, const char *owner, gpointer data_ptr); static void connman_disappeared_cb(GDBusConnection *connection, const char *name, gpointer data_ptr); static void proxy_signal_cb (GDBusProxy *proxy, const char *sender, const char *signal, GVariant *params, gpointer data_ptr); static void proxy_cb(GObject *object, GAsyncResult *res, gpointer data_ptr); static void technology_proxy_cb(GObject *object, GAsyncResult *res, gpointer data_ptr); static void get_technologies_cb(GObject *object, GAsyncResult *res, gpointer data_ptr); static void register_peer_service_cb(GObject *object, GAsyncResult *res, gpointer data_ptr); static void scan_cb(GObject *object, GAsyncResult *res, gpointer data_ptr); static void get_peers_cb(GObject *object, GAsyncResult *res, gpointer data_ptr); void connman_disappeared(); void peers_changed (GVariant *params); void proxy_cb(GAsyncResult *res); void technology_proxy_cb(GAsyncResult *res); void handle_new_peers(GVariantIter *added); void initialize_peers(); void register_peer_service(); void unregister_peer_service(); uint connman_watcher_; GDBusProxy *proxy_; GDBusProxy *technology_proxy_; Observer* observer_; std::unique_ptrarray_; std::map> peers_; }; } #endif // CONNMAN_CLIENT_H_ ================================================ FILE: p2p/connman-peer.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include "connman-peer.h" namespace P2P { /* static C callback */ void Peer::proxy_cb (GObject *object, GAsyncResult *res, gpointer data_ptr) { auto client = static_cast (data_ptr); client->proxy_cb (res); } /* static C callback */ void Peer::proxy_signal_cb (GDBusProxy *proxy, const char *sender, const char *signal, GVariant *params, gpointer data_ptr) { GVariant *property; char *name; auto peer = static_cast (data_ptr); if (g_strcmp0(signal, "PropertyChanged") != 0) return; g_variant_get (params, "(sv)", &name, &property); peer->handle_property_change (name, property); } void Peer::handle_property_change (const char *name, GVariant *property) { if (g_strcmp0(name, "State") == 0) { state_changed (g_variant_get_string (property, NULL)); } else if (g_strcmp0(name, "Name") == 0) { name_changed (g_variant_get_string (property, NULL)); } else if (g_strcmp0(name, "Services") == 0) { GVariantIter *service_array, *services; GVariant *spec_val; g_variant_get (property, "a(a{sv})", &service_array); while (g_variant_iter_loop (service_array, "(a{sv})", &services)) { const char *service_name; while (g_variant_iter_loop (services, "{sv}", &service_name, &spec_val)) { if (g_strcmp0 (service_name, "WiFiDisplayIEs") == 0) { uint8_t *bytes; gsize length; bytes = (uint8_t*)g_variant_get_fixed_array (spec_val, &length, 1); std::unique_ptr array (new P2P::InformationElementArray(length, bytes)); ie_.reset(new P2P::InformationElement (array)); } } } g_variant_iter_free (service_array); } else if (g_strcmp0(name, "IPv4") == 0) { GVariantIter *ips; GVariant *spec_val; char *name; const char *remote = ""; const char *local = ""; g_variant_get (property, "a{sv}", &ips); while (g_variant_iter_loop (ips, "{sv}", &name, &spec_val)) { if (g_strcmp0 (name, "Remote") == 0) { remote = g_variant_get_string (spec_val, NULL); } else if (g_strcmp0 (name, "Local") == 0) { local = g_variant_get_string (spec_val, NULL); } } ips_changed (remote, local); g_variant_iter_free (ips); } } /* static C callback */ void Peer::connect_cb (GObject *object, GAsyncResult *res, gpointer data_ptr) { GError *error = NULL; GDBusProxy *proxy = G_DBUS_PROXY (object); g_dbus_proxy_call_finish (proxy, res, &error); if (error) { std::cout << "connect error " << error->message << std::endl; g_clear_error (&error); return; } std::cout << "* connected "<< std::endl; } /* static C callback */ void Peer::disconnect_cb (GObject *object, GAsyncResult *res, gpointer data_ptr) { GError *error = NULL; GDBusProxy *proxy = G_DBUS_PROXY (object); g_dbus_proxy_call_finish (proxy, res, &error); if (error) { std::cout << "disconnect error " << error->message << std::endl; g_clear_error (&error); return; } std::cout << "* disconnected "<< std::endl; } void Peer::proxy_cb (GAsyncResult *result) { GError *error = NULL; proxy_ = g_dbus_proxy_new_for_bus_finish(result, &error); if (error) { std::cout << "Peer proxy error "<< std::endl; g_clear_error (&error); return; } g_signal_connect (proxy_, "g-signal", G_CALLBACK (Peer::proxy_signal_cb), this); /* TODO check the ip address in case it's up to date already */ if (observer_) observer_->on_initialized(this); } void Peer::ips_changed (const char *remote, const char *local) { if (g_strcmp0 (remote, remote_host_.c_str()) == 0 && g_strcmp0 (local, local_host_.c_str()) == 0) return; auto was_available = is_available(); if (g_strcmp0 (remote, "0.0.0.0") == 0) remote_host_.clear(); else remote_host_ = std::string(remote); if (g_strcmp0 (local, "0.0.0.0") == 0) local_host_.clear(); else local_host_ = std::string(local); if (!observer_) return; if (was_available != is_available()) observer_->on_availability_changed(this); } void Peer::state_changed (const char *state) { bool ready = (g_strcmp0 (state, "ready") == 0); if (ready_ == ready) return; auto was_available = is_available(); ready_ = ready; if (!observer_) return; if (was_available != is_available()) observer_->on_availability_changed(this); } void Peer::name_changed (const char *name) { if (g_strcmp0 (name, name_.c_str()) == 0) return; name_ = std::string (name); } Peer::Peer(const char *object_path, GVariantIter *props): observer_(NULL) { GVariant *val; const char *prop_name; while (g_variant_iter_loop (props, "{&sv}", &prop_name, &val)) { handle_property_change (prop_name, val); } if (!ie_) throw std::invalid_argument("WiFiDisplayIEs is a required property"); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, "net.connman", object_path, "net.connman.Peer", NULL, Peer::proxy_cb, this); } void Peer::connect() { g_dbus_proxy_call (proxy_, "Connect", NULL, G_DBUS_CALL_FLAGS_NONE, 60 * 1000, // is 1 minute too long? NULL, Peer::connect_cb, this); } void Peer::disconnect() { g_dbus_proxy_call (proxy_, "Disconnect", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, Peer::disconnect_cb, this); } Peer::~Peer() { if (proxy_) g_clear_object (&proxy_); } } ================================================ FILE: p2p/connman-peer.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include "information-element.h" #ifndef CONNMAN_PEER_H_ #define CONNMAN_PEER_H_ namespace P2P { class Peer { public: class Observer { public: virtual void on_availability_changed(Peer *peer) {} virtual void on_initialized(Peer *peer) {} protected: virtual ~Observer() {} }; Peer(const char *object_path, GVariantIter *property_iterator); virtual ~Peer(); void set_observer(Observer* observer) { observer_ = observer; } /* TODO add error handling for these -- maybe through observer.on_error? */ void connect(); void disconnect(); const P2P::DeviceType device_type() const { return ie_->get_device_type(); } const std::string& name() const { return name_; } const std::string& remote_host() const {return remote_host_; } const int remote_port() const { return ie_->get_rtsp_port(); } const std::string& local_host() const {return local_host_; } bool is_available() const { return ready_ && !remote_host_.empty() && !local_host_.empty(); } private: static void proxy_signal_cb (GDBusProxy *proxy, const char *sender, const char *signal, GVariant *params, gpointer data_ptr); static void proxy_cb(GObject *object, GAsyncResult *res, gpointer data_ptr); static void connect_cb (GObject *object, GAsyncResult *res, gpointer data_ptr); static void disconnect_cb (GObject *object, GAsyncResult *res, gpointer data_ptr); void ips_changed (const char *remote, const char *local); void state_changed (const char *state); void name_changed (const char *name); void proxy_cb (GAsyncResult *res); void handle_property_change (const char *name, GVariant *property); Observer *observer_; std::string name_; std::string remote_host_; std::string local_host_; bool ready_; GDBusProxy *proxy_; std::shared_ptr ie_; }; } #endif // CONNMAN_PEER_H_ ================================================ FILE: p2p/information-element.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include // htons() #include "information-element.h" namespace P2P { Subelement* new_subelement (SubelementId id) { Subelement* element; switch (id) { case DEVICE_INFORMATION: element = (Subelement*)new DeviceInformationSubelement; break; case ASSOCIATED_BSSID: element = (Subelement*)new AssociatedBSSIDSubelement; break; case COUPLED_SINK_INFORMATION: element = (Subelement*)new CoupledSinkInformationSubelement; break; default: element = NULL; break; } if (element) { /* Fill in the common values */ memset(element, 0, SubelementSize[id]); element->id = id; element->length = htons(SubelementSize[id] - 3); } return element; } void delete_subelement (Subelement *element) { switch (element->id) { case DEVICE_INFORMATION: delete ((DeviceInformationSubelement*)element); break; case ASSOCIATED_BSSID: delete ((AssociatedBSSIDSubelement*)element); break; case COUPLED_SINK_INFORMATION: delete ((CoupledSinkInformationSubelement*)element); break; default: assert(false); } } InformationElement::InformationElement(): length_(0) {} InformationElement::InformationElement(const std::unique_ptr &array) { uint pos = 0; length_ = array->length; while (length_ >= pos + 2) { SubelementId id = (SubelementId)array->bytes[pos]; size_t subelement_size = SubelementSize[id]; Subelement *element = new_subelement(id); if (element) { memcpy (element, array->bytes + pos, subelement_size); subelements_[id] = element; } pos += subelement_size; } } InformationElement::~InformationElement() { for (auto it = subelements_.begin(); it != subelements_.end(); it++){ P2P::delete_subelement ((*it).second); } subelements_.clear(); } void InformationElement::add_subelement(P2P::Subelement* subelement) { SubelementId id = (SubelementId)subelement->id; Subelement* old = subelements_[id]; if (old){ P2P::delete_subelement (old); } else { length_ += SubelementSize[id]; } subelements_[id] = subelement; } const DeviceType InformationElement::get_device_type() const { auto it = subelements_.find (DEVICE_INFORMATION); if (it == subelements_.end()) { /* FIXME : exception ? */ return DUAL_ROLE; } auto dev_info = (P2P::DeviceInformationSubelement*)(*it).second; return (DeviceType)dev_info->field1.device_type; } const int InformationElement::get_rtsp_port() const { auto it = subelements_.find (DEVICE_INFORMATION); if (it == subelements_.end()) { /* FIXME : exception ? */ return -1; } auto dev_info = (P2P::DeviceInformationSubelement*)(*it).second; return dev_info->session_management_control_port; } std::unique_ptr InformationElement::serialize () const { uint8_t pos = 0; std::unique_ptr array (new InformationElementArray(length_)); for (auto it = subelements_.begin(); it != subelements_.end(); it++) { Subelement* element = (*it).second; memcpy (array->bytes + pos, element, P2P::SubelementSize[element->id]); pos += P2P::SubelementSize[element->id]; } return array; } std::string InformationElement::to_string() const { std::string ret; auto array = serialize (); for (size_t i = 0; i < array->length; i++) { char hex[3]; sprintf(hex,"%02X", array->bytes[i]); ret += hex; } return ret; } } // namespace P2P ================================================ FILE: p2p/information-element.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef INFORMATION_ELEMENT_H_ #define INFORMATION_ELEMENT_H_ #include #include #include #include #include namespace P2P { enum DeviceType { SOURCE, PRIMARY_SINK, SECONDARY_SINK, DUAL_ROLE }; enum SubelementId { DEVICE_INFORMATION, ASSOCIATED_BSSID, AUDIO_FORMATS, VIDEO_FORMATS, FORMATS_3D, CONTENT_PROTECTION, COUPLED_SINK_INFORMATION, EXTENDED_CAPABILITY, LOCAL_IP_ADDRESS, SESSION_INFORMATION, ALTERNATIVE_MAC, }; // SubelementSize == subelement.length - 3 const uint16_t SubelementSize[] = { 9, 9, 18, 24, 20, 4, 10, 5, 11, 3, // variable: 3 + N*24, where N is number of devices connected to GO 9, }; struct __attribute__ ((packed)) Subelement { uint8_t id; uint16_t length; }; struct __attribute__ ((packed)) DeviceinformationBits1 { unsigned device_type : 2; // DeviceType unsigned coupled_sink_support_at_source : 1; unsigned coupled_sink_support_at_sink : 1; unsigned session_availability : 1; unsigned reserved : 1; unsigned service_discovery_support : 1; unsigned preferred_connectivity : 1; }; struct __attribute__ ((packed)) DeviceinformationBits2 { unsigned hdcp_support : 1; unsigned time_synchronization_support : 1; unsigned audio_unsupport_at_primary_sink : 1; unsigned audio_only_support_at_source : 1; unsigned tdls_persistent_group : 1; unsigned tdls_persistent_group_reinvoke : 1; unsigned reserved2 : 2; }; struct __attribute__ ((packed)) DeviceInformationSubelement { uint8_t id; uint16_t length; DeviceinformationBits2 field2; DeviceinformationBits1 field1; uint16_t session_management_control_port; uint16_t maximum_throughput; }; struct __attribute__ ((packed)) AssociatedBSSIDSubelement { uint8_t id; uint16_t length; uint8_t bssid[6]; }; struct __attribute__ ((packed)) CoupledSinkStatus { unsigned status : 2; unsigned reserved : 6; }; struct __attribute__ ((packed)) CoupledSinkInformationSubelement { uint8_t id; uint16_t length; CoupledSinkStatus status; uint8_t mac_address[6]; }; struct InformationElementArray { uint8_t *bytes; uint length; InformationElementArray(uint len) : length(len) { bytes = new uint8_t[length]; } InformationElementArray(uint len, uint8_t* in_bytes) : length(len) { bytes = new uint8_t[length]; memcpy (bytes, in_bytes, length); } ~InformationElementArray() { delete[] bytes; } }; Subelement* new_subelement (SubelementId id); class InformationElement { public: InformationElement(); InformationElement(const std::unique_ptr &array); virtual ~InformationElement(); void add_subelement(P2P::Subelement* subelement); const DeviceType get_device_type() const; const int get_rtsp_port() const; std::unique_ptr serialize () const; std::string to_string() const; private: void delete_subelement(P2P::Subelement* subelement); uint length_; std::map subelements_; }; } // namespace P2P #endif // INFORMATION_ELEMENT_H_ ================================================ FILE: p2p/main.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include // htons() #include "connman-client.h" #include "information-element.h" int main (int argc, const char **argv) { GMainLoop *main_loop = g_main_loop_new(NULL, TRUE); // check that packing works assert (sizeof(P2P::DeviceInformationSubelement) == P2P::SubelementSize[P2P::DEVICE_INFORMATION]); assert (sizeof(P2P::AssociatedBSSIDSubelement) == P2P::SubelementSize[P2P::ASSOCIATED_BSSID]); assert (sizeof(P2P::CoupledSinkInformationSubelement) == P2P::SubelementSize[P2P::COUPLED_SINK_INFORMATION]); // Create a information element for a simple WFD Sink P2P::InformationElement ie; auto sub_element = P2P::new_subelement(P2P::DEVICE_INFORMATION); auto dev_info = (P2P::DeviceInformationSubelement*)sub_element; dev_info->session_management_control_port = htons(8080); dev_info->maximum_throughput = htons(50); dev_info->field1.device_type = P2P::PRIMARY_SINK; dev_info->field1.session_availability = true; ie.add_subelement (sub_element); std::cout << "Registering " << ie.to_string() << std::endl; // register the P2P service with connman auto array = ie.serialize (); P2P::Client p2p_client (array); g_main_loop_run (main_loop); g_main_loop_unref (main_loop); return 0; } ================================================ FILE: p2p/test-ie.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include // htons() #include "connman-client.h" #include "information-element.h" int main (int argc, const char **argv) { // check that packing works if (sizeof(P2P::DeviceInformationSubelement) != P2P::SubelementSize[P2P::DEVICE_INFORMATION] || sizeof(P2P::AssociatedBSSIDSubelement) != P2P::SubelementSize[P2P::ASSOCIATED_BSSID] || sizeof(P2P::CoupledSinkInformationSubelement) != P2P::SubelementSize[P2P::COUPLED_SINK_INFORMATION]) { std::cout << "Subelement struct size checks failed"<< std::endl; return 1; } P2P::InformationElement ie; auto sub_element = P2P::new_subelement(P2P::DEVICE_INFORMATION); auto dev_info = (P2P::DeviceInformationSubelement*)sub_element; dev_info->session_management_control_port = htons(8080); dev_info->maximum_throughput = htons(50); dev_info->field1.device_type = P2P::PRIMARY_SINK; dev_info->field1.session_availability = true; ie.add_subelement (sub_element); ie.add_subelement (P2P::new_subelement(P2P::COUPLED_SINK_INFORMATION)); ie.add_subelement (P2P::new_subelement(P2P::ASSOCIATED_BSSID)); auto array = ie.serialize (); P2P::InformationElement ie2(array); auto array1 = ie.to_string(); auto array2 = ie2.to_string(); if (array1 != array2) { std::cout << "Expected byte array '" << array1 << "', got '" << array2 << "'" << std::endl; return 1; } return 0; } ================================================ FILE: rtsp-message-exchanges.txt ================================================ ************************************************** * RTSP messages during WFD session establishment * ************************************************** There are five different states: 1. capability negotiation A 2. capability negotiation B 3. RTSP session establishment 4. WFD session establishment 5. WFD session I'm listing the possible exchanges below, per state (except for the last state: that's a lot more work and mostly not required for POC). * = message *** = message, valid start point for a message exchange in this state SOURCE SINK MESSAGES MESSAGES ------------------------------------------------------------- STATE 1 capability negotiation A ------------------------------------------------------------- *** M1 OPTIONS --------> if M1 response == 200 send M2 <-------- * M2 OPTIONS if M2 response = 200 send M3 * M3 GET_PARAMETER --------> if M3 response == 200 move to state 2, send M4 STATE 2 capability negotiation B ------------------------------------------------------------- *** M3 GET_PARAMETER --------> * M4 SET_PARAMETER --------> (mandatory and optional parameters below) if M4 response == 200 send M5 STATE 3 RTSP session establishment ------------------------------------------------------------- *** M3 GET_PARAMETER --------> *** M4 SET_PARAMETER --------> * M5 SET_PARAMETER --------> (trigger SETUP) if M5 response == 200 send M6 <-------- * M6 SETUP if M6 response == 200 move to state 4, send M7 STATE 4 WFD session establishment ------------------------------------------------------------- *** M3 GET_PARAMETER --------> *** M5 SET_PARAMETER --------> (trigger TEARDOWN) if M5 response = 200 send M8 *** M5 SET_PARAMETER --------> (trigger PLAY) if M5 response == 200 send M7 <-------- * M7 PLAY if M7 response == 200 move to state 5, start streaming *** M8 TEARDOWN if M8 response == 200 move to state 1 STATE 5 WFD Session --------------------------------------------------------------- TODO ... ***************************** * GET/SET Method parameters * ***************************** M = mandatory O = optional These rules apply _before_ the WFD sessions is established (in other words states 1-4): request reply * M3 GET_PARAMETER ----------------------------------------------------------------- audio-codecs M M video-formats M M 3d-video-formats O M (if in request) content-protection O M (if in request) display-edid O M (if in request) coupled-sink O M (if in request) client-rtp-ports M M I2C O M (if in request) uibc-capability O M (if in request) connector-type O M (if in request) standby-resume-- O M (if in request) * M4 SET_PARAMETER audio-codecs M (if stream contains audio) video-formats M (if no preferred-display and stream contains video) 3d-video-formats M (if no preferred-display and stream includes 3d) presentation-url M client-rtp-ports M preferred-display-- O (spec error on p 111?) uibc-capability O uibc-setting O * M5 SET_PARAMETER trigger-method M ================================================ FILE: sink/CMakeLists.txt ================================================ #FIXME in the future: with cmake 2.8.12 and up it's better #to use target_compile_options or add_compile_options set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pthread -std=c++11") include_directories ("${PROJECT_SOURCE_DIR}") include_directories ("${PROJECT_SOURCE_DIR}/include") include_directories ("${PROJECT_SOURCE_DIR}/p2p") include_directories ("${PROJECT_SOURCE_DIR}/mirac_network") find_package(PkgConfig REQUIRED) pkg_check_modules (GLIB2 REQUIRED glib-2.0) include_directories(${GLIB2_INCLUDE_DIRS}) pkg_check_modules (GIO REQUIRED gio-2.0) include_directories(${GIO_INCLUDE_DIRS}) pkg_check_modules (GST REQUIRED gstreamer-1.0) include_directories(${GST_INCLUDE_DIRS}) add_executable(sink-test main.cpp sink-app.cpp sink.cpp gst_sink_media_manager.cpp) target_link_libraries (sink-test mirac wds p2p ${GIO_LIBRARIES} ${GST_LIBRARIES}) if (WDS_INSTALL_TESTS) install(PROGRAMS sink-test DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}) endif() ================================================ FILE: sink/gst_sink_media_manager.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "gst_sink_media_manager.h" GstSinkMediaManager::GstSinkMediaManager(const std::string& hostname) : gst_pipeline_(new MiracGstSink(hostname, 0)) { } void GstSinkMediaManager::Play() { gst_pipeline_->Play(); } void GstSinkMediaManager::Pause() { gst_pipeline_->Pause(); } void GstSinkMediaManager::Teardown() { gst_pipeline_->Teardown(); } bool GstSinkMediaManager::IsPaused() const { return gst_pipeline_->IsPaused(); } std::pair GstSinkMediaManager::GetLocalRtpPorts() const { return std::pair(gst_pipeline_->sink_udp_port(), 0); } void GstSinkMediaManager::SetPresentationUrl(const std::string& url) { presentation_url_ = url; } std::string GstSinkMediaManager::GetPresentationUrl() const { return presentation_url_; } void GstSinkMediaManager::SetSessionId(const std::string& session) { session_ = session; } std::string GstSinkMediaManager::GetSessionId() const { return session_; } std::vector GstSinkMediaManager::GetSupportedH264VideoCodecs() const { wds::RateAndResolutionsBitmap cea_rr; wds::RateAndResolutionsBitmap vesa_rr; wds::RateAndResolutionsBitmap hh_rr; wds::RateAndResolution i; // declare that we support all resolutions, CHP and level 4.2 // gstreamer should handle all of it :) for (i = wds::CEA640x480p60; i <= wds::CEA1920x1080p24; ++i) cea_rr.set(i); for (i = wds::VESA800x600p30; i <= wds::VESA1920x1200p30; ++i) vesa_rr.set(i); for (i = wds::HH800x480p30; i <= wds::HH848x480p60; ++i) hh_rr.set(i); return {wds::H264VideoCodec(wds::CHP, wds::k4_2, cea_rr, vesa_rr, hh_rr), wds::H264VideoCodec(wds::CBP, wds::k4_2, cea_rr, vesa_rr, hh_rr)}; } wds::NativeVideoFormat GstSinkMediaManager::GetNativeVideoFormat() const { // pick the maximum possible resolution, let gstreamer deal with it // TODO: get the actual screen size of the system return wds::NativeVideoFormat(wds::CEA1920x1080p60); } bool GstSinkMediaManager::SetOptimalVideoFormat(const wds::H264VideoFormat& optimal_format) { return true; } wds::ConnectorType GstSinkMediaManager::GetConnectorType() const { return wds::ConnectorTypeNone; } ================================================ FILE: sink/gst_sink_media_manager.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef GST_SINK_MEDIA_MANAGER_H_ #define GST_SINK_MEDIA_MANAGER_H_ #include #include "libwds/public/media_manager.h" #include "mirac-gst-sink.hpp" class GstSinkMediaManager : public wds::SinkMediaManager { public: explicit GstSinkMediaManager(const std::string& hostname); void Play() override; void Pause() override; void Teardown() override; bool IsPaused() const override; std::pair GetLocalRtpPorts() const override; void SetPresentationUrl(const std::string& url) override; std::string GetPresentationUrl() const override; void SetSessionId(const std::string& session) override; std::string GetSessionId() const override; std::vector GetSupportedH264VideoCodecs() const override; wds::NativeVideoFormat GetNativeVideoFormat() const override; bool SetOptimalVideoFormat(const wds::H264VideoFormat& optimal_format) override; wds::ConnectorType GetConnectorType() const override; private: std::string hostname_; std::string presentation_url_; std::string session_; std::unique_ptr gst_pipeline_; }; #endif // GST_SINK_MEDIA_MANAGER_H_ ================================================ FILE: sink/main.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include "mirac-glib-logging.hpp" #include "sink-app.h" #include "sink.h" static gboolean _sig_handler (gpointer data_ptr) { GMainLoop *main_loop = (GMainLoop *) data_ptr; g_main_loop_quit(main_loop); return G_SOURCE_CONTINUE; } static void parse_input_and_call_sink( const std::string& command, Sink *sink) { if (command == "teardown\n") { sink->Teardown(); return; } if (command == "pause\n") { sink->Pause(); return; } if (command == "play\n") { sink->Play(); return; } std::cout << "Received unknown command: " << command << std::endl; } static gboolean _user_input_handler ( GIOChannel* channel, GIOCondition /*condition*/, gpointer data_ptr) { GError* error = NULL; char* str = NULL; size_t len; SinkApp* app = static_cast(data_ptr); switch (g_io_channel_read_line(channel, &str, &len, NULL, &error)) { case G_IO_STATUS_NORMAL: parse_input_and_call_sink(str, &app->sink()); g_free(str); return true; case G_IO_STATUS_ERROR: std::cout << "User input error: " << error->message << std::endl; g_error_free(error); return false; case G_IO_STATUS_EOF: case G_IO_STATUS_AGAIN: return true; default: return false; } return false; } int main (int argc, char *argv[]) { InitGlibLogging(); char* hostname = NULL; int port = 7236; std::unique_ptr app; GOptionEntry main_entries[] = { { "hostname", 0, 0, G_OPTION_ARG_STRING, &hostname, "Specify remote hostname (for debugging purposes)", "host"}, { "rtsp_port", 0, 0, G_OPTION_ARG_INT, &port, "Specify remote RTSP port number (for debugging purposes), 7236 by default", "rtsp_port"}, { NULL } }; GOptionContext* context = g_option_context_new ("- WFD sink demo application\n"); g_option_context_add_main_entries (context, main_entries, NULL); g_option_context_add_group (context, gst_init_get_option_group ()); GError* error = NULL; if (!g_option_context_parse (context, &argc, &argv, &error)) { WDS_ERROR ("option parsing failed: %s", error->message); g_option_context_free(context); exit (1); } g_option_context_free(context); if (hostname) { app.reset(new SinkApp(std::string(hostname), port)); g_free (hostname); } else { app.reset(new SinkApp()); } GMainLoop *main_loop = g_main_loop_new(NULL, TRUE); g_unix_signal_add(SIGINT, _sig_handler, main_loop); g_unix_signal_add(SIGTERM, _sig_handler, main_loop); GIOChannel* io_channel = g_io_channel_unix_new (STDIN_FILENO); g_io_add_watch(io_channel, G_IO_IN, _user_input_handler, app.get()); g_io_channel_unref(io_channel); g_main_loop_run (main_loop); g_main_loop_unref (main_loop); return 0; } ================================================ FILE: sink/sink-app.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include // htons() #include "sink-app.h" #include "sink.h" #include "connman-client.h" void SinkApp::on_peer_added(P2P::Client *client, std::shared_ptr peer) { std::cout << "* New peer: " << peer->name() << std::endl; peer->set_observer (this); } void SinkApp::on_peer_removed(P2P::Client *client, std::shared_ptr peer) { std::cout << "* Peer removed: " << peer->name() << std::endl; if (peer.get() == peer_) { sink_.reset(NULL); peer_ = NULL; } } void SinkApp::on_availability_changed(P2P::Peer *peer) { if (!sink_ && peer->is_available() && peer->device_type() == P2P::SOURCE) { std::cout << "* Connecting to source at " << peer->remote_host() << ":" << ntohs(peer->remote_port()) << std::endl; sink_.reset(new Sink (peer->remote_host(), ntohs(peer->remote_port()), peer->local_host())); peer_ = peer; } else if (sink_ && !peer->is_available() && peer == peer_) { std::cout << "* Source unavailable" << std::endl; sink_.reset(NULL); peer_ = NULL; } } SinkApp::SinkApp(){ // Create a information element for a simple WFD Sink P2P::InformationElement ie; auto sub_element = P2P::new_subelement(P2P::DEVICE_INFORMATION); auto dev_info = (P2P::DeviceInformationSubelement*)sub_element; // TODO port number is a lie -- we should start the sink first, then // use the port from there (and sink should probably default to 7236) // TODO InformationElement could have constructors for this stuff... dev_info->session_management_control_port = htons(7236); dev_info->maximum_throughput = htons(50); dev_info->field1.device_type = P2P::PRIMARY_SINK; dev_info->field1.session_availability = true; ie.add_subelement (sub_element); std::cout << "* Registering Wifi Display with IE " << ie.to_string() << std::endl; // register the P2P service with connman auto array = ie.serialize (); p2p_client_.reset(new P2P::Client(array, this)); } SinkApp::SinkApp(const std::string& hostname, int port) { std::cout << "* Connecting to peer at " << hostname << ":" << port << std::endl; sink_.reset(new Sink (hostname, port, "")); } SinkApp::~SinkApp() { } ================================================ FILE: sink/sink-app.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SINK_APP_H #define SINK_APP_H #include #include "sink.h" #include "connman-client.h" class SinkApp: public P2P::Client::Observer, public P2P::Peer::Observer { public: SinkApp(); SinkApp(const std::string& hostname, int port); ~SinkApp(); Sink& sink() { return *sink_; } void on_peer_added(P2P::Client *client, std::shared_ptr peer) override; void on_peer_removed(P2P::Client *client, std::shared_ptr peer) override; void on_availability_changed(P2P::Client *client) override {}; void on_availability_changed(P2P::Peer *peer) override; void on_initialized(P2P::Peer *peer) override {}; private: std::unique_ptr p2p_client_; std::unique_ptr sink_; P2P::Peer *peer_; }; #endif // SINK_APP_H ================================================ FILE: sink/sink.cpp ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include "sink.h" #include "gst_sink_media_manager.h" Sink::Sink(const std::string& remote_host, int remote_rtsp_port, const std::string& local_host) : MiracBroker(remote_host, std::to_string(remote_rtsp_port)), local_host_(local_host) { } Sink::~Sink() {} void Sink::got_message(const std::string& message) { wfd_sink_->RTSPDataReceived(message); } void Sink::on_connected() { media_manager_.reset(new GstSinkMediaManager(local_host_)); wfd_sink_.reset(wds::Sink::Create(this, media_manager_.get())); wfd_sink_->Start(); } void Sink::on_connection_failure(ConnectionFailure failure) { switch (failure) { case CONNECTION_LOST: std::cout << "* RTSP connection lost" << std::endl; case CONNECTION_TIMEOUT: ; } } void Sink::Play() { wfd_sink_->Play(); } void Sink::Pause() { wfd_sink_->Pause(); } void Sink::Teardown() { wfd_sink_->Teardown(); } wds::Peer* Sink::Peer() const { return wfd_sink_.get(); } ================================================ FILE: sink/sink.h ================================================ /* * This file is part of Wireless Display Software for Linux OS * * Copyright (C) 2014 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SINK_H #define SINK_H #include #include "libwds/public/media_manager.h" #include "libwds/public/sink.h" #include "mirac-broker.hpp" class Sink : public MiracBroker { public: explicit Sink(const std::string& remote_host, int remote_rtsp_port, const std::string& local_host); ~Sink(); void Play(); void Pause(); void Teardown(); protected: virtual wds::Peer* Peer() const override; private: virtual void got_message(const std::string& message) override; virtual void on_connected() override; void on_connection_failure(ConnectionFailure failure) override; std::unique_ptr media_manager_; std::unique_ptr wfd_sink_; std::string local_host_; }; #endif // SINK_H