├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── app ├── .gitignore ├── CMakeLists.txt ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── dongnao │ │ └── screencapture │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── librtmp │ │ │ ├── CMakeLists.txt │ │ │ ├── COPYING │ │ │ ├── Makefile │ │ │ ├── amf.c │ │ │ ├── amf.h │ │ │ ├── bytes.h │ │ │ ├── dh.h │ │ │ ├── dhgroups.h │ │ │ ├── handshake.h │ │ │ ├── hashswf.c │ │ │ ├── http.h │ │ │ ├── librtmp.3 │ │ │ ├── librtmp.3.html │ │ │ ├── librtmp.pc.in │ │ │ ├── log.c │ │ │ ├── log.h │ │ │ ├── parseurl.c │ │ │ ├── rtmp.c │ │ │ ├── rtmp.h │ │ │ └── rtmp_sys.h │ │ ├── native-lib.c │ │ └── packt.h │ ├── java │ │ └── com │ │ │ └── dongnao │ │ │ └── screencapture │ │ │ ├── AudioCodec.java │ │ │ ├── AudioSpecificConfig.java │ │ │ ├── IFrame.java │ │ │ ├── MainActivity.java │ │ │ ├── RtmpManager.java │ │ │ └── VideoCodec.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── dongnao │ └── screencapture │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 26 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Abstraction issuesJava 46 | 47 | 48 | Android 49 | 50 | 51 | Android > Lint > Accessibility 52 | 53 | 54 | Android > Lint > Correctness 55 | 56 | 57 | Android > Lint > Correctness > Messages 58 | 59 | 60 | Android > Lint > Internationalization 61 | 62 | 63 | Android > Lint > Performance 64 | 65 | 66 | Android > Lint > Security 67 | 68 | 69 | Android > Lint > Usability 70 | 71 | 72 | Android > Lint > Usability > Icons 73 | 74 | 75 | Android Lint for Kotlin 76 | 77 | 78 | Assignment issuesJava 79 | 80 | 81 | Bitwise operation issuesJava 82 | 83 | 84 | Class structureJava 85 | 86 | 87 | Cloning issuesJava 88 | 89 | 90 | Code style issuesJava 91 | 92 | 93 | Concurrency annotation issuesJava 94 | 95 | 96 | Control FlowGroovy 97 | 98 | 99 | Control flow issuesJava 100 | 101 | 102 | Declaration redundancyJava 103 | 104 | 105 | DeclarationGroovy 106 | 107 | 108 | Encapsulation issuesJava 109 | 110 | 111 | Error handlingGroovy 112 | 113 | 114 | Error handlingJava 115 | 116 | 117 | Finalization issuesJava 118 | 119 | 120 | Groovy 121 | 122 | 123 | HTML 124 | 125 | 126 | ImportsJava 127 | 128 | 129 | Inheritance issuesJava 130 | 131 | 132 | Initialization issuesJava 133 | 134 | 135 | Internationalization issuesJava 136 | 137 | 138 | J2ME issuesJava 139 | 140 | 141 | JUnit issuesJava 142 | 143 | 144 | Java 145 | 146 | 147 | Java language level issuesJava 148 | 149 | 150 | Java language level migration aidsJava 151 | 152 | 153 | JavaBeans issuesJava 154 | 155 | 156 | Javadoc issuesJava 157 | 158 | 159 | Kotlin 160 | 161 | 162 | Naming conventionsJava 163 | 164 | 165 | Numeric issuesJava 166 | 167 | 168 | Packaging issuesJava 169 | 170 | 171 | Performance issuesJava 172 | 173 | 174 | Portability issuesJava 175 | 176 | 177 | Potentially confusing code constructsGroovy 178 | 179 | 180 | Probable bugsJava 181 | 182 | 183 | Properties Files 184 | 185 | 186 | RELAX NG 187 | 188 | 189 | Resource management issuesJava 190 | 191 | 192 | Security issuesJava 193 | 194 | 195 | Serialization issuesJava 196 | 197 | 198 | TestNGJava 199 | 200 | 201 | Threading issuesGroovy 202 | 203 | 204 | Threading issuesJava 205 | 206 | 207 | Verbose or redundant code constructsJava 208 | 209 | 210 | XML 211 | 212 | 213 | toString() issuesJava 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 235 | 236 | 237 | 238 | 239 | 1.8 240 | 241 | 246 | 247 | 248 | 249 | 250 | 251 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | 5 | cmake_minimum_required(VERSION 3.4.1) 6 | 7 | add_subdirectory(src/main/cpp/librtmp) 8 | 9 | 10 | add_library( 11 | native-lib 12 | SHARED 13 | src/main/cpp/native-lib.c ) 14 | 15 | 16 | 17 | 18 | target_link_libraries( 19 | native-lib 20 | rtmp 21 | log ) -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.1" 6 | defaultConfig { 7 | applicationId "com.dongnao.screencapture" 8 | minSdkVersion 21 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | externalNativeBuild { 14 | cmake { 15 | cppFlags "" 16 | } 17 | } 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | externalNativeBuild { 26 | cmake { 27 | path "CMakeLists.txt" 28 | } 29 | } 30 | } 31 | 32 | dependencies { 33 | compile fileTree(dir: 'libs', include: ['*.jar']) 34 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 35 | exclude group: 'com.android.support', module: 'support-annotations' 36 | }) 37 | testCompile 'junit:junit:4.12' 38 | } 39 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/xiang/develop/adt-bundle-mac-x86_64-20131030/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/dongnao/screencapture/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.dongnao.screencapture; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.dongnao.screencapture", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #关闭ssl 不支持rtmps 2 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_CRYPTO" ) 3 | #所有源文件放入 rtmp_source 变量 4 | file(GLOB rtmp_source *.c) 5 | 6 | #编译静态库 7 | add_library( 8 | rtmp 9 | STATIC 10 | ${rtmp_source} ) -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | 504 | 505 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/Makefile: -------------------------------------------------------------------------------- 1 | VERSION=v2.4 2 | 3 | prefix=/usr/local 4 | 5 | incdir=$(prefix)/include/librtmp 6 | bindir=$(prefix)/bin 7 | libdir=$(prefix)/lib 8 | mandir=$(prefix)/man 9 | BINDIR=$(DESTDIR)$(bindir) 10 | INCDIR=$(DESTDIR)$(incdir) 11 | LIBDIR=$(DESTDIR)$(libdir) 12 | MANDIR=$(DESTDIR)$(mandir) 13 | 14 | CC=$(CROSS_COMPILE)gcc 15 | LD=$(CROSS_COMPILE)ld 16 | AR=$(CROSS_COMPILE)ar 17 | 18 | SYS=posix 19 | CRYPTO=OPENSSL 20 | #CRYPTO=GNUTLS 21 | DEF_POLARSSL=-DUSE_POLARSSL 22 | DEF_OPENSSL=-DUSE_OPENSSL 23 | DEF_GNUTLS=-DUSE_GNUTLS 24 | DEF_=-DNO_CRYPTO 25 | REQ_GNUTLS=gnutls,hogweed,nettle 26 | REQ_OPENSSL=libssl,libcrypto 27 | PUB_GNUTLS=-lgmp 28 | LIBZ=-lz 29 | LIBS_posix= 30 | LIBS_darwin= 31 | LIBS_mingw=-lws2_32 -lwinmm -lgdi32 32 | LIB_GNUTLS=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ) 33 | LIB_OPENSSL=-lssl -lcrypto $(LIBZ) 34 | LIB_POLARSSL=-lpolarssl $(LIBZ) 35 | PRIVATE_LIBS=$(LIBS_$(SYS)) 36 | CRYPTO_LIB=$(LIB_$(CRYPTO)) $(PRIVATE_LIBS) 37 | CRYPTO_REQ=$(REQ_$(CRYPTO)) 38 | CRYPTO_DEF=$(DEF_$(CRYPTO)) 39 | PUBLIC_LIBS=$(PUB_$(CRYPTO)) 40 | 41 | SO_VERSION=1 42 | SOX_posix=so 43 | SOX_darwin=dylib 44 | SOX_mingw=dll 45 | SOX=$(SOX_$(SYS)) 46 | SO_posix=.$(SOX).$(SO_VERSION) 47 | SO_darwin=.$(SO_VERSION).$(SOX) 48 | SO_mingw=-$(SO_VERSION).$(SOX) 49 | SO_EXT=$(SO_$(SYS)) 50 | 51 | SODIR_posix=$(LIBDIR) 52 | SODIR_darwin=$(LIBDIR) 53 | SODIR_mingw=$(BINDIR) 54 | SODIR=$(SODIR_$(SYS)) 55 | 56 | SO_LDFLAGS_posix=-shared -Wl,-soname,$@ 57 | SO_LDFLAGS_darwin=-dynamiclib -twolevel_namespace -undefined dynamic_lookup \ 58 | -fno-common -headerpad_max_install_names -install_name $(libdir)/$@ 59 | SO_LDFLAGS_mingw=-shared -Wl,--out-implib,librtmp.dll.a 60 | SO_LDFLAGS=$(SO_LDFLAGS_$(SYS)) 61 | 62 | INSTALL_IMPLIB_posix= 63 | INSTALL_IMPLIB_darwin= 64 | INSTALL_IMPLIB_mingw=cp librtmp.dll.a $(LIBDIR) 65 | INSTALL_IMPLIB=$(INSTALL_IMPLIB_$(SYS)) 66 | 67 | SHARED=yes 68 | SODEF_yes=-fPIC 69 | SOLIB_yes=librtmp$(SO_EXT) 70 | SOINST_yes=install_so 71 | SO_DEF=$(SODEF_$(SHARED)) 72 | SO_LIB=$(SOLIB_$(SHARED)) 73 | SO_INST=$(SOINST_$(SHARED)) 74 | 75 | DEF=-DRTMPDUMP_VERSION=\"$(VERSION)\" $(CRYPTO_DEF) $(XDEF) 76 | OPT=-O2 77 | CFLAGS=-Wall $(XCFLAGS) $(INC) $(DEF) $(OPT) $(SO_DEF) 78 | LDFLAGS=$(XLDFLAGS) 79 | 80 | 81 | OBJS=rtmp.o log.o amf.o hashswf.o parseurl.o 82 | 83 | all: librtmp.a $(SO_LIB) 84 | 85 | clean: 86 | rm -f *.o *.a *.$(SOX) *$(SO_EXT) librtmp.pc 87 | 88 | librtmp.a: $(OBJS) 89 | $(AR) rs $@ $? 90 | 91 | librtmp$(SO_EXT): $(OBJS) 92 | $(CC) $(SO_LDFLAGS) $(LDFLAGS) -o $@ $^ $> $(CRYPTO_LIB) 93 | ln -sf $@ librtmp.$(SOX) 94 | 95 | log.o: log.c log.h Makefile 96 | rtmp.o: rtmp.c rtmp.h rtmp_sys.h handshake.h dh.h log.h amf.h Makefile 97 | amf.o: amf.c amf.h bytes.h log.h Makefile 98 | hashswf.o: hashswf.c http.h rtmp.h rtmp_sys.h Makefile 99 | parseurl.o: parseurl.c rtmp.h rtmp_sys.h log.h Makefile 100 | 101 | librtmp.pc: librtmp.pc.in Makefile 102 | sed -e "s;@prefix@;$(prefix);" -e "s;@libdir@;$(libdir);" \ 103 | -e "s;@VERSION@;$(VERSION);" \ 104 | -e "s;@CRYPTO_REQ@;$(CRYPTO_REQ);" \ 105 | -e "s;@PUBLIC_LIBS@;$(PUBLIC_LIBS);" \ 106 | -e "s;@PRIVATE_LIBS@;$(PRIVATE_LIBS);" librtmp.pc.in > $@ 107 | 108 | install: install_base $(SO_INST) 109 | 110 | install_base: librtmp.a librtmp.pc 111 | -mkdir -p $(INCDIR) $(LIBDIR)/pkgconfig $(MANDIR)/man3 $(SODIR) 112 | cp amf.h http.h log.h rtmp.h $(INCDIR) 113 | cp librtmp.a $(LIBDIR) 114 | cp librtmp.pc $(LIBDIR)/pkgconfig 115 | cp librtmp.3 $(MANDIR)/man3 116 | 117 | install_so: librtmp$(SO_EXT) 118 | cp librtmp$(SO_EXT) $(SODIR) 119 | $(INSTALL_IMPLIB) 120 | cd $(SODIR); ln -sf librtmp$(SO_EXT) librtmp.$(SOX) 121 | 122 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/amf.h: -------------------------------------------------------------------------------- 1 | #ifndef __AMF_H__ 2 | #define __AMF_H__ 3 | /* 4 | * Copyright (C) 2005-2008 Team XBMC 5 | * http://www.xbmc.org 6 | * Copyright (C) 2008-2009 Andrej Stepanchuk 7 | * Copyright (C) 2009-2010 Howard Chu 8 | * 9 | * This file is part of librtmp. 10 | * 11 | * librtmp is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU Lesser General Public License as 13 | * published by the Free Software Foundation; either version 2.1, 14 | * or (at your option) any later version. 15 | * 16 | * librtmp is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Lesser General Public License 22 | * along with librtmp see the file COPYING. If not, write to 23 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 24 | * Boston, MA 02110-1301, USA. 25 | * http://www.gnu.org/copyleft/lgpl.html 26 | */ 27 | 28 | #include 29 | 30 | #ifndef TRUE 31 | #define TRUE 1 32 | #define FALSE 0 33 | #endif 34 | 35 | #ifdef __cplusplus 36 | extern "C" 37 | { 38 | #endif 39 | 40 | typedef enum 41 | { AMF_NUMBER = 0, AMF_BOOLEAN, AMF_STRING, AMF_OBJECT, 42 | AMF_MOVIECLIP, /* reserved, not used */ 43 | AMF_NULL, AMF_UNDEFINED, AMF_REFERENCE, AMF_ECMA_ARRAY, AMF_OBJECT_END, 44 | AMF_STRICT_ARRAY, AMF_DATE, AMF_LONG_STRING, AMF_UNSUPPORTED, 45 | AMF_RECORDSET, /* reserved, not used */ 46 | AMF_XML_DOC, AMF_TYPED_OBJECT, 47 | AMF_AVMPLUS, /* switch to AMF3 */ 48 | AMF_INVALID = 0xff 49 | } AMFDataType; 50 | 51 | typedef enum 52 | { AMF3_UNDEFINED = 0, AMF3_NULL, AMF3_FALSE, AMF3_TRUE, 53 | AMF3_INTEGER, AMF3_DOUBLE, AMF3_STRING, AMF3_XML_DOC, AMF3_DATE, 54 | AMF3_ARRAY, AMF3_OBJECT, AMF3_XML, AMF3_BYTE_ARRAY 55 | } AMF3DataType; 56 | 57 | typedef struct AVal 58 | { 59 | char *av_val; 60 | int av_len; 61 | } AVal; 62 | #define AVC(str) {str,sizeof(str)-1} 63 | #define AVMATCH(a1,a2) ((a1)->av_len == (a2)->av_len && !memcmp((a1)->av_val,(a2)->av_val,(a1)->av_len)) 64 | 65 | struct AMFObjectProperty; 66 | 67 | typedef struct AMFObject 68 | { 69 | int o_num; 70 | struct AMFObjectProperty *o_props; 71 | } AMFObject; 72 | 73 | typedef struct AMFObjectProperty 74 | { 75 | AVal p_name; 76 | AMFDataType p_type; 77 | union 78 | { 79 | double p_number; 80 | AVal p_aval; 81 | AMFObject p_object; 82 | } p_vu; 83 | int16_t p_UTCoffset; 84 | } AMFObjectProperty; 85 | 86 | char *AMF_EncodeString(char *output, char *outend, const AVal * str); 87 | char *AMF_EncodeNumber(char *output, char *outend, double dVal); 88 | char *AMF_EncodeInt16(char *output, char *outend, short nVal); 89 | char *AMF_EncodeInt24(char *output, char *outend, int nVal); 90 | char *AMF_EncodeInt32(char *output, char *outend, int nVal); 91 | char *AMF_EncodeBoolean(char *output, char *outend, int bVal); 92 | 93 | /* Shortcuts for AMFProp_Encode */ 94 | char *AMF_EncodeNamedString(char *output, char *outend, const AVal * name, const AVal * value); 95 | char *AMF_EncodeNamedNumber(char *output, char *outend, const AVal * name, double dVal); 96 | char *AMF_EncodeNamedBoolean(char *output, char *outend, const AVal * name, int bVal); 97 | 98 | unsigned short AMF_DecodeInt16(const char *data); 99 | unsigned int AMF_DecodeInt24(const char *data); 100 | unsigned int AMF_DecodeInt32(const char *data); 101 | void AMF_DecodeString(const char *data, AVal * str); 102 | void AMF_DecodeLongString(const char *data, AVal * str); 103 | int AMF_DecodeBoolean(const char *data); 104 | double AMF_DecodeNumber(const char *data); 105 | 106 | char *AMF_Encode(AMFObject * obj, char *pBuffer, char *pBufEnd); 107 | char *AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd); 108 | char *AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd); 109 | 110 | int AMF_Decode(AMFObject * obj, const char *pBuffer, int nSize, 111 | int bDecodeName); 112 | int AMF_DecodeArray(AMFObject * obj, const char *pBuffer, int nSize, 113 | int nArrayLen, int bDecodeName); 114 | int AMF3_Decode(AMFObject * obj, const char *pBuffer, int nSize, 115 | int bDecodeName); 116 | void AMF_Dump(AMFObject * obj); 117 | void AMF_Reset(AMFObject * obj); 118 | 119 | void AMF_AddProp(AMFObject * obj, const AMFObjectProperty * prop); 120 | int AMF_CountProp(AMFObject * obj); 121 | AMFObjectProperty *AMF_GetProp(AMFObject * obj, const AVal * name, 122 | int nIndex); 123 | 124 | AMFDataType AMFProp_GetType(AMFObjectProperty * prop); 125 | void AMFProp_SetNumber(AMFObjectProperty * prop, double dval); 126 | void AMFProp_SetBoolean(AMFObjectProperty * prop, int bflag); 127 | void AMFProp_SetString(AMFObjectProperty * prop, AVal * str); 128 | void AMFProp_SetObject(AMFObjectProperty * prop, AMFObject * obj); 129 | 130 | void AMFProp_GetName(AMFObjectProperty * prop, AVal * name); 131 | void AMFProp_SetName(AMFObjectProperty * prop, AVal * name); 132 | double AMFProp_GetNumber(AMFObjectProperty * prop); 133 | int AMFProp_GetBoolean(AMFObjectProperty * prop); 134 | void AMFProp_GetString(AMFObjectProperty * prop, AVal * str); 135 | void AMFProp_GetObject(AMFObjectProperty * prop, AMFObject * obj); 136 | 137 | int AMFProp_IsValid(AMFObjectProperty * prop); 138 | 139 | char *AMFProp_Encode(AMFObjectProperty * prop, char *pBuffer, char *pBufEnd); 140 | int AMF3Prop_Decode(AMFObjectProperty * prop, const char *pBuffer, 141 | int nSize, int bDecodeName); 142 | int AMFProp_Decode(AMFObjectProperty * prop, const char *pBuffer, 143 | int nSize, int bDecodeName); 144 | 145 | void AMFProp_Dump(AMFObjectProperty * prop); 146 | void AMFProp_Reset(AMFObjectProperty * prop); 147 | 148 | typedef struct AMF3ClassDef 149 | { 150 | AVal cd_name; 151 | char cd_externalizable; 152 | char cd_dynamic; 153 | int cd_num; 154 | AVal *cd_props; 155 | } AMF3ClassDef; 156 | 157 | void AMF3CD_AddProp(AMF3ClassDef * cd, AVal * prop); 158 | AVal *AMF3CD_GetProp(AMF3ClassDef * cd, int idx); 159 | 160 | #ifdef __cplusplus 161 | } 162 | #endif 163 | 164 | #endif /* __AMF_H__ */ 165 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/bytes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2005-2008 Team XBMC 3 | * http://www.xbmc.org 4 | * Copyright (C) 2008-2009 Andrej Stepanchuk 5 | * Copyright (C) 2009-2010 Howard Chu 6 | * 7 | * This file is part of librtmp. 8 | * 9 | * librtmp is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as 11 | * published by the Free Software Foundation; either version 2.1, 12 | * or (at your option) any later version. 13 | * 14 | * librtmp is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with librtmp see the file COPYING. If not, write to 21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 | * Boston, MA 02110-1301, USA. 23 | * http://www.gnu.org/copyleft/lgpl.html 24 | */ 25 | 26 | #ifndef __BYTES_H__ 27 | #define __BYTES_H__ 28 | 29 | #include 30 | 31 | #ifdef _WIN32 32 | /* Windows is little endian only */ 33 | #define __LITTLE_ENDIAN 1234 34 | #define __BIG_ENDIAN 4321 35 | #define __BYTE_ORDER __LITTLE_ENDIAN 36 | #define __FLOAT_WORD_ORDER __BYTE_ORDER 37 | 38 | typedef unsigned char uint8_t; 39 | 40 | #else /* !_WIN32 */ 41 | 42 | #include 43 | 44 | #if defined(BYTE_ORDER) && !defined(__BYTE_ORDER) 45 | #define __BYTE_ORDER BYTE_ORDER 46 | #endif 47 | 48 | #if defined(BIG_ENDIAN) && !defined(__BIG_ENDIAN) 49 | #define __BIG_ENDIAN BIG_ENDIAN 50 | #endif 51 | 52 | #if defined(LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN) 53 | #define __LITTLE_ENDIAN LITTLE_ENDIAN 54 | #endif 55 | 56 | #endif /* !_WIN32 */ 57 | 58 | /* define default endianness */ 59 | #ifndef __LITTLE_ENDIAN 60 | #define __LITTLE_ENDIAN 1234 61 | #endif 62 | 63 | #ifndef __BIG_ENDIAN 64 | #define __BIG_ENDIAN 4321 65 | #endif 66 | 67 | #ifndef __BYTE_ORDER 68 | #warning "Byte order not defined on your system, assuming little endian!" 69 | #define __BYTE_ORDER __LITTLE_ENDIAN 70 | #endif 71 | 72 | /* ok, we assume to have the same float word order and byte order if float word order is not defined */ 73 | #ifndef __FLOAT_WORD_ORDER 74 | #warning "Float word order not defined, assuming the same as byte order!" 75 | #define __FLOAT_WORD_ORDER __BYTE_ORDER 76 | #endif 77 | 78 | #if !defined(__BYTE_ORDER) || !defined(__FLOAT_WORD_ORDER) 79 | #error "Undefined byte or float word order!" 80 | #endif 81 | 82 | #if __FLOAT_WORD_ORDER != __BIG_ENDIAN && __FLOAT_WORD_ORDER != __LITTLE_ENDIAN 83 | #error "Unknown/unsupported float word order!" 84 | #endif 85 | 86 | #if __BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN 87 | #error "Unknown/unsupported byte order!" 88 | #endif 89 | 90 | #endif 91 | 92 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/dh.h: -------------------------------------------------------------------------------- 1 | /* RTMPDump - Diffie-Hellmann Key Exchange 2 | * Copyright (C) 2009 Andrej Stepanchuk 3 | * Copyright (C) 2009-2010 Howard Chu 4 | * 5 | * This file is part of librtmp. 6 | * 7 | * librtmp is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1, 10 | * or (at your option) any later version. 11 | * 12 | * librtmp is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with librtmp see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | * Boston, MA 02110-1301, USA. 21 | * http://www.gnu.org/copyleft/lgpl.html 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #ifdef USE_POLARSSL 31 | #include 32 | typedef mpi * MP_t; 33 | #define MP_new(m) m = malloc(sizeof(mpi)); mpi_init(m) 34 | #define MP_set_w(mpi, w) mpi_lset(mpi, w) 35 | #define MP_cmp(u, v) mpi_cmp_mpi(u, v) 36 | #define MP_set(u, v) mpi_copy(u, v) 37 | #define MP_sub_w(mpi, w) mpi_sub_int(mpi, mpi, w) 38 | #define MP_cmp_1(mpi) mpi_cmp_int(mpi, 1) 39 | #define MP_modexp(r, y, q, p) mpi_exp_mod(r, y, q, p, NULL) 40 | #define MP_free(mpi) mpi_free(mpi); free(mpi) 41 | #define MP_gethex(u, hex, res) MP_new(u); res = mpi_read_string(u, 16, hex) == 0 42 | #define MP_bytes(u) mpi_size(u) 43 | #define MP_setbin(u,buf,len) mpi_write_binary(u,buf,len) 44 | #define MP_getbin(u,buf,len) MP_new(u); mpi_read_binary(u,buf,len) 45 | 46 | typedef struct MDH { 47 | MP_t p; 48 | MP_t g; 49 | MP_t pub_key; 50 | MP_t priv_key; 51 | long length; 52 | dhm_context ctx; 53 | } MDH; 54 | 55 | #define MDH_new() calloc(1,sizeof(MDH)) 56 | #define MDH_free(vp) {MDH *_dh = vp; dhm_free(&_dh->ctx); MP_free(_dh->p); MP_free(_dh->g); MP_free(_dh->pub_key); MP_free(_dh->priv_key); free(_dh);} 57 | 58 | static int MDH_generate_key(MDH *dh) 59 | { 60 | unsigned char out[2]; 61 | MP_set(&dh->ctx.P, dh->p); 62 | MP_set(&dh->ctx.G, dh->g); 63 | dh->ctx.len = 128; 64 | dhm_make_public(&dh->ctx, 1024, out, 1, havege_random, &RTMP_TLS_ctx->hs); 65 | MP_new(dh->pub_key); 66 | MP_new(dh->priv_key); 67 | MP_set(dh->pub_key, &dh->ctx.GX); 68 | MP_set(dh->priv_key, &dh->ctx.X); 69 | return 1; 70 | } 71 | 72 | static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh) 73 | { 74 | MP_set(&dh->ctx.GY, pub); 75 | dhm_calc_secret(&dh->ctx, secret, &len); 76 | return 0; 77 | } 78 | 79 | #elif defined(USE_GNUTLS) 80 | #include 81 | #include 82 | #include 83 | typedef mpz_ptr MP_t; 84 | #define MP_new(m) m = malloc(sizeof(*m)); mpz_init2(m, 1) 85 | #define MP_set_w(mpi, w) mpz_set_ui(mpi, w) 86 | #define MP_cmp(u, v) mpz_cmp(u, v) 87 | #define MP_set(u, v) mpz_set(u, v) 88 | #define MP_sub_w(mpi, w) mpz_sub_ui(mpi, mpi, w) 89 | #define MP_cmp_1(mpi) mpz_cmp_ui(mpi, 1) 90 | #define MP_modexp(r, y, q, p) mpz_powm(r, y, q, p) 91 | #define MP_free(mpi) mpz_clear(mpi); free(mpi) 92 | #define MP_gethex(u, hex, res) u = malloc(sizeof(*u)); mpz_init2(u, 1); res = (mpz_set_str(u, hex, 16) == 0) 93 | #define MP_bytes(u) (mpz_sizeinbase(u, 2) + 7) / 8 94 | #define MP_setbin(u,buf,len) nettle_mpz_get_str_256(len,buf,u) 95 | #define MP_getbin(u,buf,len) u = malloc(sizeof(*u)); mpz_init2(u, 1); nettle_mpz_set_str_256_u(u,len,buf) 96 | 97 | typedef struct MDH { 98 | MP_t p; 99 | MP_t g; 100 | MP_t pub_key; 101 | MP_t priv_key; 102 | long length; 103 | } MDH; 104 | 105 | #define MDH_new() calloc(1,sizeof(MDH)) 106 | #define MDH_free(dh) do {MP_free(((MDH*)(dh))->p); MP_free(((MDH*)(dh))->g); MP_free(((MDH*)(dh))->pub_key); MP_free(((MDH*)(dh))->priv_key); free(dh);} while(0) 107 | 108 | static int MDH_generate_key(MDH *dh) 109 | { 110 | int num_bytes; 111 | uint32_t seed; 112 | gmp_randstate_t rs; 113 | 114 | num_bytes = (mpz_sizeinbase(dh->p, 2) + 7) / 8 - 1; 115 | if (num_bytes <= 0 || num_bytes > 18000) 116 | return 0; 117 | 118 | dh->priv_key = calloc(1, sizeof(*dh->priv_key)); 119 | if (!dh->priv_key) 120 | return 0; 121 | mpz_init2(dh->priv_key, 1); 122 | gnutls_rnd(GNUTLS_RND_RANDOM, &seed, sizeof(seed)); 123 | gmp_randinit_mt(rs); 124 | gmp_randseed_ui(rs, seed); 125 | mpz_urandomb(dh->priv_key, rs, num_bytes); 126 | gmp_randclear(rs); 127 | 128 | dh->pub_key = calloc(1, sizeof(*dh->pub_key)); 129 | if (!dh->pub_key) 130 | return 0; 131 | mpz_init2(dh->pub_key, 1); 132 | if (!dh->pub_key) { 133 | mpz_clear(dh->priv_key); 134 | free(dh->priv_key); 135 | return 0; 136 | } 137 | 138 | mpz_powm(dh->pub_key, dh->g, dh->priv_key, dh->p); 139 | 140 | return 1; 141 | } 142 | 143 | static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh) 144 | { 145 | mpz_ptr k; 146 | int num_bytes; 147 | 148 | num_bytes = (mpz_sizeinbase(dh->p, 2) + 7) / 8; 149 | if (num_bytes <= 0 || num_bytes > 18000) 150 | return -1; 151 | 152 | k = calloc(1, sizeof(*k)); 153 | if (!k) 154 | return -1; 155 | mpz_init2(k, 1); 156 | 157 | mpz_powm(k, pub, dh->priv_key, dh->p); 158 | nettle_mpz_get_str_256(len, secret, k); 159 | mpz_clear(k); 160 | free(k); 161 | 162 | /* return the length of the shared secret key like DH_compute_key */ 163 | return len; 164 | } 165 | 166 | #else /* USE_OPENSSL */ 167 | #include 168 | #include 169 | 170 | typedef BIGNUM * MP_t; 171 | #define MP_new(m) m = BN_new() 172 | #define MP_set_w(mpi, w) BN_set_word(mpi, w) 173 | #define MP_cmp(u, v) BN_cmp(u, v) 174 | #define MP_set(u, v) BN_copy(u, v) 175 | #define MP_sub_w(mpi, w) BN_sub_word(mpi, w) 176 | #define MP_cmp_1(mpi) BN_cmp(mpi, BN_value_one()) 177 | #define MP_modexp(r, y, q, p) do {BN_CTX *ctx = BN_CTX_new(); BN_mod_exp(r, y, q, p, ctx); BN_CTX_free(ctx);} while(0) 178 | #define MP_free(mpi) BN_free(mpi) 179 | #define MP_gethex(u, hex, res) res = BN_hex2bn(&u, hex) 180 | #define MP_bytes(u) BN_num_bytes(u) 181 | #define MP_setbin(u,buf,len) BN_bn2bin(u,buf) 182 | #define MP_getbin(u,buf,len) u = BN_bin2bn(buf,len,0) 183 | 184 | #define MDH DH 185 | #define MDH_new() DH_new() 186 | #define MDH_free(dh) DH_free(dh) 187 | #define MDH_generate_key(dh) DH_generate_key(dh) 188 | #define MDH_compute_key(secret, seclen, pub, dh) DH_compute_key(secret, pub, dh) 189 | 190 | #endif 191 | 192 | #include "log.h" 193 | #include "dhgroups.h" 194 | 195 | /* RFC 2631, Section 2.1.5, http://www.ietf.org/rfc/rfc2631.txt */ 196 | static int 197 | isValidPublicKey(MP_t y, MP_t p, MP_t q) 198 | { 199 | int ret = TRUE; 200 | MP_t bn; 201 | assert(y); 202 | 203 | MP_new(bn); 204 | assert(bn); 205 | 206 | /* y must lie in [2,p-1] */ 207 | MP_set_w(bn, 1); 208 | if (MP_cmp(y, bn) < 0) 209 | { 210 | RTMP_Log(RTMP_LOGERROR, "DH public key must be at least 2"); 211 | ret = FALSE; 212 | goto failed; 213 | } 214 | 215 | /* bn = p-2 */ 216 | MP_set(bn, p); 217 | MP_sub_w(bn, 1); 218 | if (MP_cmp(y, bn) > 0) 219 | { 220 | RTMP_Log(RTMP_LOGERROR, "DH public key must be at most p-2"); 221 | ret = FALSE; 222 | goto failed; 223 | } 224 | 225 | /* Verify with Sophie-Germain prime 226 | * 227 | * This is a nice test to make sure the public key position is calculated 228 | * correctly. This test will fail in about 50% of the cases if applied to 229 | * random data. 230 | */ 231 | if (q) 232 | { 233 | /* y must fulfill y^q mod p = 1 */ 234 | MP_modexp(bn, y, q, p); 235 | 236 | if (MP_cmp_1(bn) != 0) 237 | { 238 | RTMP_Log(RTMP_LOGWARNING, "DH public key does not fulfill y^q mod p = 1"); 239 | } 240 | } 241 | 242 | failed: 243 | MP_free(bn); 244 | return ret; 245 | } 246 | 247 | static MDH * 248 | DHInit(int nKeyBits) 249 | { 250 | size_t res; 251 | MDH *dh = MDH_new(); 252 | 253 | if (!dh) 254 | goto failed; 255 | 256 | MP_new(dh->g); 257 | 258 | if (!dh->g) 259 | goto failed; 260 | 261 | MP_gethex(dh->p, P1024, res); /* prime P1024, see dhgroups.h */ 262 | if (!res) 263 | { 264 | goto failed; 265 | } 266 | 267 | MP_set_w(dh->g, 2); /* base 2 */ 268 | 269 | dh->length = nKeyBits; 270 | return dh; 271 | 272 | failed: 273 | if (dh) 274 | MDH_free(dh); 275 | 276 | return 0; 277 | } 278 | 279 | static int 280 | DHGenerateKey(MDH *dh) 281 | { 282 | size_t res = 0; 283 | if (!dh) 284 | return 0; 285 | 286 | while (!res) 287 | { 288 | MP_t q1 = NULL; 289 | 290 | if (!MDH_generate_key(dh)) 291 | return 0; 292 | 293 | MP_gethex(q1, Q1024, res); 294 | assert(res); 295 | 296 | res = isValidPublicKey(dh->pub_key, dh->p, q1); 297 | if (!res) 298 | { 299 | MP_free(dh->pub_key); 300 | MP_free(dh->priv_key); 301 | dh->pub_key = dh->priv_key = 0; 302 | } 303 | 304 | MP_free(q1); 305 | } 306 | return 1; 307 | } 308 | 309 | /* fill pubkey with the public key in BIG ENDIAN order 310 | * 00 00 00 00 00 x1 x2 x3 ..... 311 | */ 312 | 313 | static int 314 | DHGetPublicKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen) 315 | { 316 | int len; 317 | if (!dh || !dh->pub_key) 318 | return 0; 319 | 320 | len = MP_bytes(dh->pub_key); 321 | if (len <= 0 || len > (int) nPubkeyLen) 322 | return 0; 323 | 324 | memset(pubkey, 0, nPubkeyLen); 325 | MP_setbin(dh->pub_key, pubkey + (nPubkeyLen - len), len); 326 | return 1; 327 | } 328 | 329 | #if 0 /* unused */ 330 | static int 331 | DHGetPrivateKey(MDH *dh, uint8_t *privkey, size_t nPrivkeyLen) 332 | { 333 | if (!dh || !dh->priv_key) 334 | return 0; 335 | 336 | int len = MP_bytes(dh->priv_key); 337 | if (len <= 0 || len > (int) nPrivkeyLen) 338 | return 0; 339 | 340 | memset(privkey, 0, nPrivkeyLen); 341 | MP_setbin(dh->priv_key, privkey + (nPrivkeyLen - len), len); 342 | return 1; 343 | } 344 | #endif 345 | 346 | /* computes the shared secret key from the private MDH value and the 347 | * other party's public key (pubkey) 348 | */ 349 | static int 350 | DHComputeSharedSecretKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen, 351 | uint8_t *secret) 352 | { 353 | MP_t q1 = NULL, pubkeyBn = NULL; 354 | size_t len; 355 | int res; 356 | 357 | if (!dh || !secret || nPubkeyLen >= INT_MAX) 358 | return -1; 359 | 360 | MP_getbin(pubkeyBn, pubkey, nPubkeyLen); 361 | if (!pubkeyBn) 362 | return -1; 363 | 364 | MP_gethex(q1, Q1024, len); 365 | assert(len); 366 | 367 | if (isValidPublicKey(pubkeyBn, dh->p, q1)) 368 | res = MDH_compute_key(secret, nPubkeyLen, pubkeyBn, dh); 369 | else 370 | res = -1; 371 | 372 | MP_free(q1); 373 | MP_free(pubkeyBn); 374 | 375 | return res; 376 | } 377 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/dhgroups.h: -------------------------------------------------------------------------------- 1 | /* librtmp - Diffie-Hellmann Key Exchange 2 | * Copyright (C) 2009 Andrej Stepanchuk 3 | * 4 | * This file is part of librtmp. 5 | * 6 | * librtmp is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as 8 | * published by the Free Software Foundation; either version 2.1, 9 | * or (at your option) any later version. 10 | * 11 | * librtmp is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with librtmp see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | * http://www.gnu.org/copyleft/lgpl.html 21 | */ 22 | 23 | /* from RFC 3526, see http://www.ietf.org/rfc/rfc3526.txt */ 24 | 25 | /* 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 } */ 26 | #define P768 \ 27 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 28 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 29 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 30 | "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF" 31 | 32 | /* 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } */ 33 | #define P1024 \ 34 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 35 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 36 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 37 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 38 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \ 39 | "FFFFFFFFFFFFFFFF" 40 | 41 | /* Group morder largest prime factor: */ 42 | #define Q1024 \ 43 | "7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68" \ 44 | "948127044533E63A0105DF531D89CD9128A5043CC71A026E" \ 45 | "F7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122" \ 46 | "F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6" \ 47 | "F71C35FDAD44CFD2D74F9208BE258FF324943328F67329C0" \ 48 | "FFFFFFFFFFFFFFFF" 49 | 50 | /* 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } */ 51 | #define P1536 \ 52 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 53 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 54 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 55 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 56 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 57 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 58 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 59 | "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" 60 | 61 | /* 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } */ 62 | #define P2048 \ 63 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 64 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 65 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 66 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 67 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 68 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 69 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 70 | "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ 71 | "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ 72 | "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ 73 | "15728E5A8AACAA68FFFFFFFFFFFFFFFF" 74 | 75 | /* 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } */ 76 | #define P3072 \ 77 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 78 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 79 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 80 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 81 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 82 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 83 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 84 | "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ 85 | "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ 86 | "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ 87 | "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ 88 | "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ 89 | "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ 90 | "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ 91 | "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ 92 | "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" 93 | 94 | /* 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } */ 95 | #define P4096 \ 96 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 97 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 98 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 99 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 100 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 101 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 102 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 103 | "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ 104 | "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ 105 | "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ 106 | "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ 107 | "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ 108 | "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ 109 | "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ 110 | "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ 111 | "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ 112 | "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ 113 | "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ 114 | "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ 115 | "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ 116 | "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ 117 | "FFFFFFFFFFFFFFFF" 118 | 119 | /* 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } */ 120 | #define P6144 \ 121 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 122 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 123 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 124 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 125 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 126 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 127 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 128 | "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ 129 | "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ 130 | "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ 131 | "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ 132 | "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ 133 | "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ 134 | "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ 135 | "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ 136 | "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ 137 | "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ 138 | "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ 139 | "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ 140 | "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ 141 | "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" \ 142 | "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" \ 143 | "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" \ 144 | "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" \ 145 | "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" \ 146 | "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" \ 147 | "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" \ 148 | "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" \ 149 | "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" \ 150 | "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" \ 151 | "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" \ 152 | "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF" 153 | 154 | /* 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } */ 155 | #define P8192 \ 156 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 157 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 158 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 159 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 160 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 161 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 162 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 163 | "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ 164 | "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ 165 | "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ 166 | "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ 167 | "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ 168 | "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ 169 | "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ 170 | "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ 171 | "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ 172 | "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ 173 | "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ 174 | "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ 175 | "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ 176 | "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" \ 177 | "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" \ 178 | "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" \ 179 | "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" \ 180 | "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" \ 181 | "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" \ 182 | "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" \ 183 | "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" \ 184 | "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" \ 185 | "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" \ 186 | "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" \ 187 | "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" \ 188 | "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" \ 189 | "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" \ 190 | "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" \ 191 | "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" \ 192 | "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" \ 193 | "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" \ 194 | "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" \ 195 | "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" \ 196 | "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" \ 197 | "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" \ 198 | "60C980DD98EDD3DFFFFFFFFFFFFFFFFF" 199 | 200 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/hashswf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009-2010 Howard Chu 3 | * 4 | * This file is part of librtmp. 5 | * 6 | * librtmp is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as 8 | * published by the Free Software Foundation; either version 2.1, 9 | * or (at your option) any later version. 10 | * 11 | * librtmp is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with librtmp see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | * http://www.gnu.org/copyleft/lgpl.html 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "rtmp_sys.h" 30 | #include "log.h" 31 | #include "http.h" 32 | 33 | #ifdef CRYPTO 34 | #ifdef USE_POLARSSL 35 | #include 36 | #ifndef SHA256_DIGEST_LENGTH 37 | #define SHA256_DIGEST_LENGTH 32 38 | #endif 39 | #define HMAC_CTX sha2_context 40 | #define HMAC_setup(ctx, key, len) sha2_hmac_starts(&ctx, (unsigned char *)key, len, 0) 41 | #define HMAC_crunch(ctx, buf, len) sha2_hmac_update(&ctx, buf, len) 42 | #define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; sha2_hmac_finish(&ctx, dig) 43 | #define HMAC_close(ctx) 44 | #elif defined(USE_GNUTLS) 45 | #include 46 | #ifndef SHA256_DIGEST_LENGTH 47 | #define SHA256_DIGEST_LENGTH 32 48 | #endif 49 | #undef HMAC_CTX 50 | #define HMAC_CTX struct hmac_sha256_ctx 51 | #define HMAC_setup(ctx, key, len) hmac_sha256_set_key(&ctx, len, key) 52 | #define HMAC_crunch(ctx, buf, len) hmac_sha256_update(&ctx, len, buf) 53 | #define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; hmac_sha256_digest(&ctx, SHA256_DIGEST_LENGTH, dig) 54 | #define HMAC_close(ctx) 55 | #else /* USE_OPENSSL */ 56 | #include 57 | #include 58 | #include 59 | #include 60 | #define HMAC_setup(ctx, key, len) HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, (unsigned char *)key, len, EVP_sha256(), 0) 61 | #define HMAC_crunch(ctx, buf, len) HMAC_Update(&ctx, (unsigned char *)buf, len) 62 | #define HMAC_finish(ctx, dig, dlen) HMAC_Final(&ctx, (unsigned char *)dig, &dlen); 63 | #define HMAC_close(ctx) HMAC_CTX_cleanup(&ctx) 64 | #endif 65 | 66 | extern void RTMP_TLS_Init(); 67 | extern TLS_CTX RTMP_TLS_ctx; 68 | 69 | #include 70 | 71 | #endif /* CRYPTO */ 72 | 73 | #define AGENT "Mozilla/5.0" 74 | 75 | HTTPResult 76 | HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb) 77 | { 78 | char *host, *path; 79 | char *p1, *p2; 80 | char hbuf[256]; 81 | int port = 80; 82 | #ifdef CRYPTO 83 | int ssl = 0; 84 | #endif 85 | int hlen, flen = 0; 86 | int rc, i; 87 | int len_known; 88 | HTTPResult ret = HTTPRES_OK; 89 | struct sockaddr_in sa; 90 | RTMPSockBuf sb = {0}; 91 | 92 | http->status = -1; 93 | 94 | memset(&sa, 0, sizeof(struct sockaddr_in)); 95 | sa.sin_family = AF_INET; 96 | 97 | /* we only handle http here */ 98 | if (strncasecmp(url, "http", 4)) 99 | return HTTPRES_BAD_REQUEST; 100 | 101 | if (url[4] == 's') 102 | { 103 | #ifdef CRYPTO 104 | ssl = 1; 105 | port = 443; 106 | if (!RTMP_TLS_ctx) 107 | RTMP_TLS_Init(); 108 | #else 109 | return HTTPRES_BAD_REQUEST; 110 | #endif 111 | } 112 | 113 | p1 = strchr(url + 4, ':'); 114 | if (!p1 || strncmp(p1, "://", 3)) 115 | return HTTPRES_BAD_REQUEST; 116 | 117 | host = p1 + 3; 118 | path = strchr(host, '/'); 119 | hlen = path - host; 120 | strncpy(hbuf, host, hlen); 121 | hbuf[hlen] = '\0'; 122 | host = hbuf; 123 | p1 = strrchr(host, ':'); 124 | if (p1) 125 | { 126 | *p1++ = '\0'; 127 | port = atoi(p1); 128 | } 129 | 130 | sa.sin_addr.s_addr = inet_addr(host); 131 | if (sa.sin_addr.s_addr == INADDR_NONE) 132 | { 133 | struct hostent *hp = gethostbyname(host); 134 | if (!hp || !hp->h_addr) 135 | return HTTPRES_LOST_CONNECTION; 136 | sa.sin_addr = *(struct in_addr *)hp->h_addr; 137 | } 138 | sa.sin_port = htons(port); 139 | sb.sb_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 140 | if (sb.sb_socket == -1) 141 | return HTTPRES_LOST_CONNECTION; 142 | i = 143 | sprintf(sb.sb_buf, 144 | "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\nReferer: %.*s\r\n", 145 | path, AGENT, host, (int)(path - url + 1), url); 146 | if (http->date[0]) 147 | i += sprintf(sb.sb_buf + i, "If-Modified-Since: %s\r\n", http->date); 148 | i += sprintf(sb.sb_buf + i, "\r\n"); 149 | 150 | if (connect 151 | (sb.sb_socket, (struct sockaddr *)&sa, sizeof(struct sockaddr)) < 0) 152 | { 153 | ret = HTTPRES_LOST_CONNECTION; 154 | goto leave; 155 | } 156 | #ifdef CRYPTO 157 | if (ssl) 158 | { 159 | #ifdef NO_SSL 160 | RTMP_Log(RTMP_LOGERROR, "%s, No SSL/TLS support", __FUNCTION__); 161 | ret = HTTPRES_BAD_REQUEST; 162 | goto leave; 163 | #else 164 | TLS_client(RTMP_TLS_ctx, sb.sb_ssl); 165 | TLS_setfd(sb.sb_ssl, sb.sb_socket); 166 | if (TLS_connect(sb.sb_ssl) < 0) 167 | { 168 | RTMP_Log(RTMP_LOGERROR, "%s, TLS_Connect failed", __FUNCTION__); 169 | ret = HTTPRES_LOST_CONNECTION; 170 | goto leave; 171 | } 172 | #endif 173 | } 174 | #endif 175 | RTMPSockBuf_Send(&sb, sb.sb_buf, i); 176 | 177 | /* set timeout */ 178 | #define HTTP_TIMEOUT 5 179 | { 180 | SET_RCVTIMEO(tv, HTTP_TIMEOUT); 181 | if (setsockopt 182 | (sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv))) 183 | { 184 | RTMP_Log(RTMP_LOGERROR, "%s, Setting socket timeout to %ds failed!", 185 | __FUNCTION__, HTTP_TIMEOUT); 186 | } 187 | } 188 | 189 | sb.sb_size = 0; 190 | sb.sb_timedout = FALSE; 191 | if (RTMPSockBuf_Fill(&sb) < 1) 192 | { 193 | ret = HTTPRES_LOST_CONNECTION; 194 | goto leave; 195 | } 196 | if (strncmp(sb.sb_buf, "HTTP/1", 6)) 197 | { 198 | ret = HTTPRES_BAD_REQUEST; 199 | goto leave; 200 | } 201 | 202 | p1 = strchr(sb.sb_buf, ' '); 203 | rc = atoi(p1 + 1); 204 | http->status = rc; 205 | 206 | if (rc >= 300) 207 | { 208 | if (rc == 304) 209 | { 210 | ret = HTTPRES_OK_NOT_MODIFIED; 211 | goto leave; 212 | } 213 | else if (rc == 404) 214 | ret = HTTPRES_NOT_FOUND; 215 | else if (rc >= 500) 216 | ret = HTTPRES_SERVER_ERROR; 217 | else if (rc >= 400) 218 | ret = HTTPRES_BAD_REQUEST; 219 | else 220 | ret = HTTPRES_REDIRECTED; 221 | } 222 | 223 | p1 = memchr(sb.sb_buf, '\n', sb.sb_size); 224 | if (!p1) 225 | { 226 | ret = HTTPRES_BAD_REQUEST; 227 | goto leave; 228 | } 229 | sb.sb_start = p1 + 1; 230 | sb.sb_size -= sb.sb_start - sb.sb_buf; 231 | 232 | while ((p2 = memchr(sb.sb_start, '\r', sb.sb_size))) 233 | { 234 | if (*sb.sb_start == '\r') 235 | { 236 | sb.sb_start += 2; 237 | sb.sb_size -= 2; 238 | break; 239 | } 240 | else 241 | if (!strncasecmp 242 | (sb.sb_start, "Content-Length: ", sizeof("Content-Length: ") - 1)) 243 | { 244 | flen = atoi(sb.sb_start + sizeof("Content-Length: ") - 1); 245 | } 246 | else 247 | if (!strncasecmp 248 | (sb.sb_start, "Last-Modified: ", sizeof("Last-Modified: ") - 1)) 249 | { 250 | *p2 = '\0'; 251 | strcpy(http->date, sb.sb_start + sizeof("Last-Modified: ") - 1); 252 | } 253 | p2 += 2; 254 | sb.sb_size -= p2 - sb.sb_start; 255 | sb.sb_start = p2; 256 | if (sb.sb_size < 1) 257 | { 258 | if (RTMPSockBuf_Fill(&sb) < 1) 259 | { 260 | ret = HTTPRES_LOST_CONNECTION; 261 | goto leave; 262 | } 263 | } 264 | } 265 | 266 | len_known = flen > 0; 267 | while ((!len_known || flen > 0) && 268 | (sb.sb_size > 0 || RTMPSockBuf_Fill(&sb) > 0)) 269 | { 270 | cb(sb.sb_start, 1, sb.sb_size, http->data); 271 | if (len_known) 272 | flen -= sb.sb_size; 273 | http->size += sb.sb_size; 274 | sb.sb_size = 0; 275 | } 276 | 277 | if (flen > 0) 278 | ret = HTTPRES_LOST_CONNECTION; 279 | 280 | leave: 281 | RTMPSockBuf_Close(&sb); 282 | return ret; 283 | } 284 | 285 | #ifdef CRYPTO 286 | 287 | #define CHUNK 16384 288 | 289 | struct info 290 | { 291 | z_stream *zs; 292 | HMAC_CTX ctx; 293 | int first; 294 | int zlib; 295 | int size; 296 | }; 297 | 298 | static size_t 299 | swfcrunch(void *ptr, size_t size, size_t nmemb, void *stream) 300 | { 301 | struct info *i = stream; 302 | char *p = ptr; 303 | size_t len = size * nmemb; 304 | 305 | if (i->first) 306 | { 307 | i->first = 0; 308 | /* compressed? */ 309 | if (!strncmp(p, "CWS", 3)) 310 | { 311 | *p = 'F'; 312 | i->zlib = 1; 313 | } 314 | HMAC_crunch(i->ctx, (unsigned char *)p, 8); 315 | p += 8; 316 | len -= 8; 317 | i->size = 8; 318 | } 319 | 320 | if (i->zlib) 321 | { 322 | unsigned char out[CHUNK]; 323 | i->zs->next_in = (unsigned char *)p; 324 | i->zs->avail_in = len; 325 | do 326 | { 327 | i->zs->avail_out = CHUNK; 328 | i->zs->next_out = out; 329 | inflate(i->zs, Z_NO_FLUSH); 330 | len = CHUNK - i->zs->avail_out; 331 | i->size += len; 332 | HMAC_crunch(i->ctx, out, len); 333 | } 334 | while (i->zs->avail_out == 0); 335 | } 336 | else 337 | { 338 | i->size += len; 339 | HMAC_crunch(i->ctx, (unsigned char *)p, len); 340 | } 341 | return size * nmemb; 342 | } 343 | 344 | static int tzoff; 345 | static int tzchecked; 346 | 347 | #define JAN02_1980 318340800 348 | 349 | static const char *monthtab[12] = { "Jan", "Feb", "Mar", 350 | "Apr", "May", "Jun", 351 | "Jul", "Aug", "Sep", 352 | "Oct", "Nov", "Dec" 353 | }; 354 | static const char *days[] = 355 | { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 356 | 357 | /* Parse an HTTP datestamp into Unix time */ 358 | static time_t 359 | make_unix_time(char *s) 360 | { 361 | struct tm time; 362 | int i, ysub = 1900, fmt = 0; 363 | char *month; 364 | char *n; 365 | time_t res; 366 | 367 | if (s[3] != ' ') 368 | { 369 | fmt = 1; 370 | if (s[3] != ',') 371 | ysub = 0; 372 | } 373 | for (n = s; *n; ++n) 374 | if (*n == '-' || *n == ':') 375 | *n = ' '; 376 | 377 | time.tm_mon = 0; 378 | n = strchr(s, ' '); 379 | if (fmt) 380 | { 381 | /* Day, DD-MMM-YYYY HH:MM:SS GMT */ 382 | time.tm_mday = strtol(n + 1, &n, 0); 383 | month = n + 1; 384 | n = strchr(month, ' '); 385 | time.tm_year = strtol(n + 1, &n, 0); 386 | time.tm_hour = strtol(n + 1, &n, 0); 387 | time.tm_min = strtol(n + 1, &n, 0); 388 | time.tm_sec = strtol(n + 1, NULL, 0); 389 | } 390 | else 391 | { 392 | /* Unix ctime() format. Does not conform to HTTP spec. */ 393 | /* Day MMM DD HH:MM:SS YYYY */ 394 | month = n + 1; 395 | n = strchr(month, ' '); 396 | while (isspace(*n)) 397 | n++; 398 | time.tm_mday = strtol(n, &n, 0); 399 | time.tm_hour = strtol(n + 1, &n, 0); 400 | time.tm_min = strtol(n + 1, &n, 0); 401 | time.tm_sec = strtol(n + 1, &n, 0); 402 | time.tm_year = strtol(n + 1, NULL, 0); 403 | } 404 | if (time.tm_year > 100) 405 | time.tm_year -= ysub; 406 | 407 | for (i = 0; i < 12; i++) 408 | if (!strncasecmp(month, monthtab[i], 3)) 409 | { 410 | time.tm_mon = i; 411 | break; 412 | } 413 | time.tm_isdst = 0; /* daylight saving is never in effect in GMT */ 414 | 415 | /* this is normally the value of extern int timezone, but some 416 | * braindead C libraries don't provide it. 417 | */ 418 | if (!tzchecked) 419 | { 420 | struct tm *tc; 421 | time_t then = JAN02_1980; 422 | tc = localtime(&then); 423 | tzoff = (12 - tc->tm_hour) * 3600 + tc->tm_min * 60 + tc->tm_sec; 424 | tzchecked = 1; 425 | } 426 | res = mktime(&time); 427 | /* Unfortunately, mktime() assumes the input is in local time, 428 | * not GMT, so we have to correct it here. 429 | */ 430 | if (res != -1) 431 | res += tzoff; 432 | return res; 433 | } 434 | 435 | /* Convert a Unix time to a network time string 436 | * Weekday, DD-MMM-YYYY HH:MM:SS GMT 437 | */ 438 | static void 439 | strtime(time_t * t, char *s) 440 | { 441 | struct tm *tm; 442 | 443 | tm = gmtime((time_t *) t); 444 | sprintf(s, "%s, %02d %s %d %02d:%02d:%02d GMT", 445 | days[tm->tm_wday], tm->tm_mday, monthtab[tm->tm_mon], 446 | tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec); 447 | } 448 | 449 | #define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf)) 450 | 451 | int 452 | RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, 453 | int age) 454 | { 455 | FILE *f = NULL; 456 | char *path, date[64], cctim[64]; 457 | long pos = 0; 458 | time_t ctim = -1, cnow; 459 | int i, got = 0, ret = 0; 460 | unsigned int hlen; 461 | struct info in = { 0 }; 462 | struct HTTP_ctx http = { 0 }; 463 | HTTPResult httpres; 464 | z_stream zs = { 0 }; 465 | AVal home, hpre; 466 | 467 | date[0] = '\0'; 468 | #ifdef _WIN32 469 | #ifdef XBMC4XBOX 470 | hpre.av_val = "Q:"; 471 | hpre.av_len = 2; 472 | home.av_val = "\\UserData"; 473 | #else 474 | hpre.av_val = getenv("HOMEDRIVE"); 475 | hpre.av_len = strlen(hpre.av_val); 476 | home.av_val = getenv("HOMEPATH"); 477 | #endif 478 | #define DIRSEP "\\" 479 | 480 | #else /* !_WIN32 */ 481 | hpre.av_val = ""; 482 | hpre.av_len = 0; 483 | home.av_val = getenv("HOME"); 484 | #define DIRSEP "/" 485 | #endif 486 | if (!home.av_val) 487 | home.av_val = "."; 488 | home.av_len = strlen(home.av_val); 489 | 490 | /* SWF hash info is cached in a fixed-format file. 491 | * url: 492 | * ctim: HTTP datestamp of when we last checked it. 493 | * date: HTTP datestamp of the SWF's last modification. 494 | * size: SWF size in hex 495 | * hash: SWF hash in hex 496 | * 497 | * These fields must be present in this order. All fields 498 | * besides URL are fixed size. 499 | */ 500 | path = malloc(hpre.av_len + home.av_len + sizeof(DIRSEP ".swfinfo")); 501 | sprintf(path, "%s%s" DIRSEP ".swfinfo", hpre.av_val, home.av_val); 502 | 503 | f = fopen(path, "r+"); 504 | while (f) 505 | { 506 | char buf[4096], *file, *p; 507 | 508 | file = strchr(url, '/'); 509 | if (!file) 510 | break; 511 | file += 2; 512 | file = strchr(file, '/'); 513 | if (!file) 514 | break; 515 | file++; 516 | hlen = file - url; 517 | p = strrchr(file, '/'); 518 | if (p) 519 | file = p; 520 | else 521 | file--; 522 | 523 | while (fgets(buf, sizeof(buf), f)) 524 | { 525 | char *r1; 526 | 527 | got = 0; 528 | 529 | if (strncmp(buf, "url: ", 5)) 530 | continue; 531 | if (strncmp(buf + 5, url, hlen)) 532 | continue; 533 | r1 = strrchr(buf, '/'); 534 | i = strlen(r1); 535 | r1[--i] = '\0'; 536 | if (strncmp(r1, file, i)) 537 | continue; 538 | pos = ftell(f); 539 | while (got < 4 && fgets(buf, sizeof(buf), f)) 540 | { 541 | if (!strncmp(buf, "size: ", 6)) 542 | { 543 | *size = strtol(buf + 6, NULL, 16); 544 | got++; 545 | } 546 | else if (!strncmp(buf, "hash: ", 6)) 547 | { 548 | unsigned char *ptr = hash, *in = (unsigned char *)buf + 6; 549 | int l = strlen((char *)in) - 1; 550 | for (i = 0; i < l; i += 2) 551 | *ptr++ = (HEX2BIN(in[i]) << 4) | HEX2BIN(in[i + 1]); 552 | got++; 553 | } 554 | else if (!strncmp(buf, "date: ", 6)) 555 | { 556 | buf[strlen(buf) - 1] = '\0'; 557 | strncpy(date, buf + 6, sizeof(date)); 558 | got++; 559 | } 560 | else if (!strncmp(buf, "ctim: ", 6)) 561 | { 562 | buf[strlen(buf) - 1] = '\0'; 563 | ctim = make_unix_time(buf + 6); 564 | got++; 565 | } 566 | else if (!strncmp(buf, "url: ", 5)) 567 | break; 568 | } 569 | break; 570 | } 571 | break; 572 | } 573 | 574 | cnow = time(NULL); 575 | /* If we got a cache time, see if it's young enough to use directly */ 576 | if (age && ctim > 0) 577 | { 578 | ctim = cnow - ctim; 579 | ctim /= 3600 * 24; /* seconds to days */ 580 | if (ctim < age) /* ok, it's new enough */ 581 | goto out; 582 | } 583 | 584 | in.first = 1; 585 | HMAC_setup(in.ctx, "Genuine Adobe Flash Player 001", 30); 586 | inflateInit(&zs); 587 | in.zs = &zs; 588 | 589 | http.date = date; 590 | http.data = ∈ 591 | 592 | httpres = HTTP_get(&http, url, swfcrunch); 593 | 594 | inflateEnd(&zs); 595 | 596 | if (httpres != HTTPRES_OK && httpres != HTTPRES_OK_NOT_MODIFIED) 597 | { 598 | ret = -1; 599 | if (httpres == HTTPRES_LOST_CONNECTION) 600 | RTMP_Log(RTMP_LOGERROR, "%s: connection lost while downloading swfurl %s", 601 | __FUNCTION__, url); 602 | else if (httpres == HTTPRES_NOT_FOUND) 603 | RTMP_Log(RTMP_LOGERROR, "%s: swfurl %s not found", __FUNCTION__, url); 604 | else 605 | RTMP_Log(RTMP_LOGERROR, "%s: couldn't contact swfurl %s (HTTP error %d)", 606 | __FUNCTION__, url, http.status); 607 | } 608 | else 609 | { 610 | if (got && pos) 611 | fseek(f, pos, SEEK_SET); 612 | else 613 | { 614 | char *q; 615 | if (!f) 616 | f = fopen(path, "w"); 617 | if (!f) 618 | { 619 | int err = errno; 620 | RTMP_Log(RTMP_LOGERROR, 621 | "%s: couldn't open %s for writing, errno %d (%s)", 622 | __FUNCTION__, path, err, strerror(err)); 623 | ret = -1; 624 | goto out; 625 | } 626 | fseek(f, 0, SEEK_END); 627 | q = strchr(url, '?'); 628 | if (q) 629 | i = q - url; 630 | else 631 | i = strlen(url); 632 | 633 | fprintf(f, "url: %.*s\n", i, url); 634 | } 635 | strtime(&cnow, cctim); 636 | fprintf(f, "ctim: %s\n", cctim); 637 | 638 | if (!in.first) 639 | { 640 | HMAC_finish(in.ctx, hash, hlen); 641 | *size = in.size; 642 | 643 | fprintf(f, "date: %s\n", date); 644 | fprintf(f, "size: %08x\n", in.size); 645 | fprintf(f, "hash: "); 646 | for (i = 0; i < SHA256_DIGEST_LENGTH; i++) 647 | fprintf(f, "%02x", hash[i]); 648 | fprintf(f, "\n"); 649 | } 650 | } 651 | HMAC_close(in.ctx); 652 | out: 653 | free(path); 654 | if (f) 655 | fclose(f); 656 | return ret; 657 | } 658 | #else 659 | int 660 | RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, 661 | int age) 662 | { 663 | return -1; 664 | } 665 | #endif 666 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/http.h: -------------------------------------------------------------------------------- 1 | #ifndef __RTMP_HTTP_H__ 2 | #define __RTMP_HTTP_H__ 3 | /* 4 | * Copyright (C) 2010 Howard Chu 5 | * Copyright (C) 2010 Antti Ajanki 6 | * 7 | * This file is part of librtmp. 8 | * 9 | * librtmp is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as 11 | * published by the Free Software Foundation; either version 2.1, 12 | * or (at your option) any later version. 13 | * 14 | * librtmp is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with librtmp see the file COPYING. If not, write to 21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 | * Boston, MA 02110-1301, USA. 23 | * http://www.gnu.org/copyleft/lgpl.html 24 | */ 25 | 26 | typedef enum { 27 | HTTPRES_OK, /* result OK */ 28 | HTTPRES_OK_NOT_MODIFIED, /* not modified since last request */ 29 | HTTPRES_NOT_FOUND, /* not found */ 30 | HTTPRES_BAD_REQUEST, /* client error */ 31 | HTTPRES_SERVER_ERROR, /* server reported an error */ 32 | HTTPRES_REDIRECTED, /* resource has been moved */ 33 | HTTPRES_LOST_CONNECTION /* connection lost while waiting for data */ 34 | } HTTPResult; 35 | 36 | struct HTTP_ctx { 37 | char *date; 38 | int size; 39 | int status; 40 | void *data; 41 | }; 42 | 43 | typedef size_t (HTTP_read_callback)(void *ptr, size_t size, size_t nmemb, void *stream); 44 | 45 | HTTPResult HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/librtmp.3: -------------------------------------------------------------------------------- 1 | .TH LIBRTMP 3 "2011-07-20" "RTMPDump v2.4" 2 | .\" Copyright 2011 Howard Chu. 3 | .\" Copying permitted according to the GNU General Public License V2. 4 | .SH NAME 5 | librtmp \- RTMPDump Real-Time Messaging Protocol API 6 | .SH LIBRARY 7 | RTMPDump RTMP (librtmp, -lrtmp) 8 | .SH SYNOPSIS 9 | .B #include 10 | .SH DESCRIPTION 11 | The Real-Time Messaging Protocol (RTMP) is used for streaming 12 | multimedia content across a TCP/IP network. This API provides most client 13 | functions and a few server functions needed to support RTMP, RTMP tunneled 14 | in HTTP (RTMPT), encrypted RTMP (RTMPE), RTMP over SSL/TLS (RTMPS) and 15 | tunneled variants of these encrypted types (RTMPTE, RTMPTS). The basic 16 | RTMP specification has been published by Adobe but this API was 17 | reverse-engineered without use of the Adobe specification. As such, it may 18 | deviate from any published specifications but it usually duplicates the 19 | actual behavior of the original Adobe clients. 20 | 21 | The RTMPDump software package includes a basic client utility program 22 | in 23 | .BR rtmpdump (1), 24 | some sample servers, and a library used to provide programmatic access 25 | to the RTMP protocol. This man page gives an overview of the RTMP 26 | library routines. These routines are found in the -lrtmp library. Many 27 | other routines are also available, but they are not documented yet. 28 | 29 | The basic interaction is as follows. A session handle is created using 30 | .BR RTMP_Alloc () 31 | and initialized using 32 | .BR RTMP_Init (). 33 | All session parameters are provided using 34 | .BR RTMP_SetupURL (). 35 | The network connection is established using 36 | .BR RTMP_Connect (), 37 | and then the RTMP session is established using 38 | .BR RTMP_ConnectStream (). 39 | The stream is read using 40 | .BR RTMP_Read (). 41 | A client can publish a stream by calling 42 | .BR RTMP_EnableWrite () 43 | before the 44 | .BR RTMP_Connect () 45 | call, and then using 46 | .BR RTMP_Write () 47 | after the session is established. 48 | While a stream is playing it may be paused and unpaused using 49 | .BR RTMP_Pause (). 50 | The stream playback position can be moved using 51 | .BR RTMP_Seek (). 52 | When 53 | .BR RTMP_Read () 54 | returns 0 bytes, the stream is complete and may be closed using 55 | .BR RTMP_Close (). 56 | The session handle is freed using 57 | .BR RTMP_Free (). 58 | 59 | All data is transferred using FLV format. The basic session requires 60 | an RTMP URL. The RTMP URL format is of the form 61 | .nf 62 | rtmp[t][e|s]://hostname[:port][/app[/playpath]] 63 | .fi 64 | 65 | Plain rtmp, as well as tunneled and encrypted sessions are supported. 66 | 67 | Additional options may be specified by appending space-separated 68 | key=value pairs to the URL. Special characters in values may need 69 | to be escaped to prevent misinterpretation by the option parser. 70 | The escape encoding uses a backslash followed by two hexadecimal digits 71 | representing the ASCII value of the character. E.g., spaces must 72 | be escaped as \fB\\20\fP and backslashes must be escaped as \fB\\5c\fP. 73 | .SH OPTIONS 74 | .SS "Network Parameters" 75 | These options define how to connect to the media server. 76 | .TP 77 | .BI socks= host:port 78 | Use the specified SOCKS4 proxy. 79 | .SS "Connection Parameters" 80 | These options define the content of the RTMP Connect request packet. 81 | If correct values are not provided, the media server will reject the 82 | connection attempt. 83 | .TP 84 | .BI app= name 85 | Name of application to connect to on the RTMP server. Overrides 86 | the app in the RTMP URL. Sometimes the librtmp URL parser cannot 87 | determine the app name automatically, so it must be given explicitly 88 | using this option. 89 | .TP 90 | .BI tcUrl= url 91 | URL of the target stream. Defaults to rtmp[t][e|s]://host[:port]/app. 92 | .TP 93 | .BI pageUrl= url 94 | URL of the web page in which the media was embedded. By default no 95 | value will be sent. 96 | .TP 97 | .BI swfUrl= url 98 | URL of the SWF player for the media. By default no value will be sent. 99 | .TP 100 | .BI flashVer= version 101 | Version of the Flash plugin used to run the SWF player. The 102 | default is "LNX 10,0,32,18". 103 | .TP 104 | .BI conn= type:data 105 | Append arbitrary AMF data to the Connect message. The type 106 | must be B for Boolean, N for number, S for string, O for object, or Z 107 | for null. For Booleans the data must be either 0 or 1 for FALSE or TRUE, 108 | respectively. Likewise for Objects the data must be 0 or 1 to end or 109 | begin an object, respectively. Data items in subobjects may be named, by 110 | prefixing the type with 'N' and specifying the name before the value, e.g. 111 | NB:myFlag:1. This option may be used multiple times to construct arbitrary 112 | AMF sequences. E.g. 113 | .nf 114 | conn=B:1 conn=S:authMe conn=O:1 conn=NN:code:1.23 conn=NS:flag:ok conn=O:0 115 | .fi 116 | .SS "Session Parameters" 117 | These options take effect after the Connect request has succeeded. 118 | .TP 119 | .BI playpath= path 120 | Overrides the playpath parsed from the RTMP URL. Sometimes the 121 | rtmpdump URL parser cannot determine the correct playpath 122 | automatically, so it must be given explicitly using this option. 123 | .TP 124 | .BI playlist= 0|1 125 | If the value is 1 or TRUE, issue a set_playlist command before sending the 126 | play command. The playlist will just contain the current playpath. If the 127 | value is 0 or FALSE, the set_playlist command will not be sent. The 128 | default is FALSE. 129 | .TP 130 | .BI live= 0|1 131 | Specify that the media is a live stream. No resuming or seeking in 132 | live streams is possible. 133 | .TP 134 | .BI subscribe= path 135 | Name of live stream to subscribe to. Defaults to 136 | .IR playpath . 137 | .TP 138 | .BI start= num 139 | Start at 140 | .I num 141 | seconds into the stream. Not valid for live streams. 142 | .TP 143 | .BI stop= num 144 | Stop at 145 | .I num 146 | seconds into the stream. 147 | .TP 148 | .BI buffer= num 149 | Set buffer time to 150 | .I num 151 | milliseconds. The default is 30000. 152 | .TP 153 | .BI timeout= num 154 | Timeout the session after 155 | .I num 156 | seconds without receiving any data from the server. The default is 120. 157 | .SS "Security Parameters" 158 | These options handle additional authentication requests from the server. 159 | .TP 160 | .BI token= key 161 | Key for SecureToken response, used if the server requires SecureToken 162 | authentication. 163 | .TP 164 | .BI jtv= JSON 165 | JSON token used by legacy Justin.tv servers. Invokes NetStream.Authenticate.UsherToken 166 | .TP 167 | .BI swfVfy= 0|1 168 | If the value is 1 or TRUE, the SWF player is retrieved from the 169 | specified 170 | .I swfUrl 171 | for performing SWF Verification. The SWF hash and size (used in the 172 | verification step) are computed automatically. Also the SWF information is 173 | cached in a 174 | .I .swfinfo 175 | file in the user's home directory, so that it doesn't need to be retrieved 176 | and recalculated every time. The .swfinfo file records 177 | the SWF URL, the time it was fetched, the modification timestamp of the SWF 178 | file, its size, and its hash. By default, the cached info will be used 179 | for 30 days before re-checking. 180 | .TP 181 | .BI swfAge= days 182 | Specify how many days to use the cached SWF info before re-checking. Use 183 | 0 to always check the SWF URL. Note that if the check shows that the 184 | SWF file has the same modification timestamp as before, it will not be 185 | retrieved again. 186 | .SH EXAMPLES 187 | An example character string suitable for use with 188 | .BR RTMP_SetupURL (): 189 | .nf 190 | "rtmp://flashserver:1935/ondemand/thefile swfUrl=http://flashserver/player.swf swfVfy=1" 191 | .fi 192 | .SH ENVIRONMENT 193 | .TP 194 | .B HOME 195 | The value of 196 | .RB $ HOME 197 | is used as the location for the 198 | .I .swfinfo 199 | file. 200 | .SH FILES 201 | .TP 202 | .I $HOME/.swfinfo 203 | Cache of SWF Verification information 204 | .SH "SEE ALSO" 205 | .BR rtmpdump (1), 206 | .BR rtmpgw (8) 207 | .SH AUTHORS 208 | Andrej Stepanchuk, Howard Chu, The Flvstreamer Team 209 | .br 210 | 211 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/librtmp.3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | LIBRTMP(3): 4 | 5 | 6 | 8 | 9 | 11 |
LIBRTMP(3)LIBRTMP(3) 7 |
RTMPDump v2.42011-07-20LIBRTMP(3) 10 |


    12 | 14 |
15 | 16 |

NAME

    17 | librtmp − RTMPDump Real-Time Messaging Protocol API 18 |
19 | 20 |

LIBRARY

    21 | RTMPDump RTMP (librtmp, -lrtmp) 22 |
23 | 24 |

SYNOPSIS

    25 | #include <librtmp/rtmp.h> 26 |
27 | 28 |

DESCRIPTION

    29 | The Real-Time Messaging Protocol (RTMP) is used for streaming 30 | multimedia content across a TCP/IP network. This API provides most client 31 | functions and a few server functions needed to support RTMP, RTMP tunneled 32 | in HTTP (RTMPT), encrypted RTMP (RTMPE), RTMP over SSL/TLS (RTMPS) and 33 | tunneled variants of these encrypted types (RTMPTE, RTMPTS). The basic 34 | RTMP specification has been published by Adobe but this API was 35 | reverse-engineered without use of the Adobe specification. As such, it may 36 | deviate from any published specifications but it usually duplicates the 37 | actual behavior of the original Adobe clients. 38 |

    39 | The RTMPDump software package includes a basic client utility program 40 | in 41 | rtmpdump(1), 42 | some sample servers, and a library used to provide programmatic access 43 | to the RTMP protocol. This man page gives an overview of the RTMP 44 | library routines. These routines are found in the -lrtmp library. Many 45 | other routines are also available, but they are not documented yet. 46 |

    47 | The basic interaction is as follows. A session handle is created using 48 | RTMP_Alloc() 49 | and initialized using 50 | RTMP_Init(). 51 | All session parameters are provided using 52 | RTMP_SetupURL(). 53 | The network connection is established using 54 | RTMP_Connect(), 55 | and then the RTMP session is established using 56 | RTMP_ConnectStream(). 57 | The stream is read using 58 | RTMP_Read(). 59 | A client can publish a stream by calling 60 | RTMP_EnableWrite() 61 | before the 62 | RTMP_Connect() 63 | call, and then using 64 | RTMP_Write() 65 | after the session is established. 66 | While a stream is playing it may be paused and unpaused using 67 | RTMP_Pause(). 68 | The stream playback position can be moved using 69 | RTMP_Seek(). 70 | When 71 | RTMP_Read() 72 | returns 0 bytes, the stream is complete and may be closed using 73 | RTMP_Close(). 74 | The session handle is freed using 75 | RTMP_Free(). 76 |

    77 | All data is transferred using FLV format. The basic session requires 78 | an RTMP URL. The RTMP URL format is of the form 79 |

     80 |   rtmp[t][e|s]://hostname[:port][/app[/playpath]]
     81 | 
    82 |

    83 | Plain rtmp, as well as tunneled and encrypted sessions are supported. 84 |

    85 | Additional options may be specified by appending space-separated 86 | key=value pairs to the URL. Special characters in values may need 87 | to be escaped to prevent misinterpretation by the option parser. 88 | The escape encoding uses a backslash followed by two hexadecimal digits 89 | representing the ASCII value of the character. E.g., spaces must 90 | be escaped as \20 and backslashes must be escaped as \5c. 91 |

92 | 93 |

OPTIONS

    94 |
95 | 96 |

Network Parameters

    97 | These options define how to connect to the media server. 98 |

    99 |

    100 | socks=host:port 101 |
    102 | Use the specified SOCKS4 proxy. 103 |
    104 |
105 | 106 |

Connection Parameters

    107 | These options define the content of the RTMP Connect request packet. 108 | If correct values are not provided, the media server will reject the 109 | connection attempt. 110 |

    111 |

    112 | app=name 113 |
    114 | Name of application to connect to on the RTMP server. Overrides 115 | the app in the RTMP URL. Sometimes the librtmp URL parser cannot 116 | determine the app name automatically, so it must be given explicitly 117 | using this option. 118 |
    119 |

    120 |

    121 | tcUrl=url 122 |
    123 | URL of the target stream. Defaults to rtmp[t][e|s]://host[:port]/app. 124 |
    125 |

    126 |

    127 | pageUrl=url 128 |
    129 | URL of the web page in which the media was embedded. By default no 130 | value will be sent. 131 |
    132 |

    133 |

    134 | swfUrl=url 135 |
    136 | URL of the SWF player for the media. By default no value will be sent. 137 |
    138 |

    139 |

    140 | flashVer=version 141 |
    142 | Version of the Flash plugin used to run the SWF player. The 143 | default is "LNX 10,0,32,18". 144 |
    145 |

    146 |

    147 | conn=type:data 148 |
    149 | Append arbitrary AMF data to the Connect message. The type 150 | must be B for Boolean, N for number, S for string, O for object, or Z 151 | for null. For Booleans the data must be either 0 or 1 for FALSE or TRUE, 152 | respectively. Likewise for Objects the data must be 0 or 1 to end or 153 | begin an object, respectively. Data items in subobjects may be named, by 154 | prefixing the type with 'N' and specifying the name before the value, e.g. 155 | NB:myFlag:1. This option may be used multiple times to construct arbitrary 156 | AMF sequences. E.g. 157 |
    158 |   conn=B:1 conn=S:authMe conn=O:1 conn=NN:code:1.23 conn=NS:flag:ok conn=O:0
    159 | 
    160 |
    161 |
162 | 163 |

Session Parameters

    164 | These options take effect after the Connect request has succeeded. 165 |

    166 |

    167 | playpath=path 168 |
    169 | Overrides the playpath parsed from the RTMP URL. Sometimes the 170 | rtmpdump URL parser cannot determine the correct playpath 171 | automatically, so it must be given explicitly using this option. 172 |
    173 |

    174 |

    175 | playlist=0|1 176 |
    177 | If the value is 1 or TRUE, issue a set_playlist command before sending the 178 | play command. The playlist will just contain the current playpath. If the 179 | value is 0 or FALSE, the set_playlist command will not be sent. The 180 | default is FALSE. 181 |
    182 |

    183 |

    184 | live=0|1 185 |
    186 | Specify that the media is a live stream. No resuming or seeking in 187 | live streams is possible. 188 |
    189 |

    190 |

    191 | subscribe=path 192 |
    193 | Name of live stream to subscribe to. Defaults to 194 | playpath. 195 |
    196 |

    197 |

    198 | start=num 199 |
    200 | Start at 201 | num 202 | seconds into the stream. Not valid for live streams. 203 |
    204 |

    205 |

    206 | stop=num 207 |
    208 | Stop at 209 | num 210 | seconds into the stream. 211 |
    212 |

    213 |

    214 | buffer=num 215 |
    216 | Set buffer time to 217 | num 218 | milliseconds. The default is 30000. 219 |
    220 |

    221 |

    222 | timeout=num 223 |
    224 | Timeout the session after 225 | num 226 | seconds without receiving any data from the server. The default is 120. 227 |
    228 |
229 | 230 |

Security Parameters

    231 | These options handle additional authentication requests from the server. 232 |

    233 |

    234 | token=key 235 |
    236 | Key for SecureToken response, used if the server requires SecureToken 237 | authentication. 238 |
    239 |

    240 |

    241 | jtv=JSON 242 |
    243 | JSON token used by legacy Justin.tv servers. Invokes NetStream.Authenticate.UsherToken 244 |
    245 |

    246 |

    247 | swfVfy=0|1 248 |
    249 | If the value is 1 or TRUE, the SWF player is retrieved from the 250 | specified 251 | swfUrl 252 | for performing SWF Verification. The SWF hash and size (used in the 253 | verification step) are computed automatically. Also the SWF information is 254 | cached in a 255 | .swfinfo 256 | file in the user's home directory, so that it doesn't need to be retrieved 257 | and recalculated every time. The .swfinfo file records 258 | the SWF URL, the time it was fetched, the modification timestamp of the SWF 259 | file, its size, and its hash. By default, the cached info will be used 260 | for 30 days before re-checking. 261 |
    262 |

    263 |

    264 | swfAge=days 265 |
    266 | Specify how many days to use the cached SWF info before re-checking. Use 267 | 0 to always check the SWF URL. Note that if the check shows that the 268 | SWF file has the same modification timestamp as before, it will not be 269 | retrieved again. 270 |
    271 |
272 | 273 |

EXAMPLES

    274 | An example character string suitable for use with 275 | RTMP_SetupURL(): 276 |
    277 |   "rtmp://flashserver:1935/ondemand/thefile swfUrl=http://flashserver/player.swf swfVfy=1"
    278 | 
    279 |
280 | 281 |

ENVIRONMENT

    282 |

    283 |

    284 | HOME 285 |
    286 | The value of 287 | $HOME 288 | is used as the location for the 289 | .swfinfo 290 | file. 291 |
    292 |
293 | 294 |

FILES

    295 |

    296 |

    297 | $HOME/.swfinfo 298 |
    299 | Cache of SWF Verification information 300 |
    301 |
302 | 303 |

SEE ALSO

307 | 308 |

AUTHORS

313 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/librtmp.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=${prefix} 3 | libdir=@libdir@ 4 | incdir=${prefix}/include 5 | 6 | Name: librtmp 7 | Description: RTMP implementation 8 | Version: @VERSION@ 9 | Requires: @CRYPTO_REQ@ 10 | URL: http://rtmpdump.mplayerhq.hu 11 | Libs: -L${libdir} -lrtmp -lz @PUBLIC_LIBS@ 12 | Libs.private: @PRIVATE_LIBS@ 13 | Cflags: -I${incdir} 14 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2009 Andrej Stepanchuk 3 | * Copyright (C) 2009-2010 Howard Chu 4 | * 5 | * This file is part of librtmp. 6 | * 7 | * librtmp is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1, 10 | * or (at your option) any later version. 11 | * 12 | * librtmp is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with librtmp see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | * Boston, MA 02110-1301, USA. 21 | * http://www.gnu.org/copyleft/lgpl.html 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "rtmp_sys.h" 31 | #include "log.h" 32 | 33 | #define MAX_PRINT_LEN 2048 34 | 35 | RTMP_LogLevel RTMP_debuglevel = RTMP_LOGERROR; 36 | 37 | static int neednl; 38 | 39 | static FILE *fmsg; 40 | 41 | static RTMP_LogCallback rtmp_log_default, *cb = rtmp_log_default; 42 | 43 | static const char *levels[] = { 44 | "CRIT", "ERROR", "WARNING", "INFO", 45 | "DEBUG", "DEBUG2" 46 | }; 47 | 48 | static void rtmp_log_default(int level, const char *format, va_list vl) 49 | { 50 | char str[MAX_PRINT_LEN]=""; 51 | 52 | vsnprintf(str, MAX_PRINT_LEN-1, format, vl); 53 | 54 | /* Filter out 'no-name' */ 55 | if ( RTMP_debuglevel RTMP_debuglevel ) 97 | return; 98 | 99 | va_start(args, format); 100 | cb(level, format, args); 101 | va_end(args); 102 | } 103 | 104 | static const char hexdig[] = "0123456789abcdef"; 105 | 106 | void RTMP_LogHex(int level, const uint8_t *data, unsigned long len) 107 | { 108 | unsigned long i; 109 | char line[50], *ptr; 110 | 111 | if ( level > RTMP_debuglevel ) 112 | return; 113 | 114 | ptr = line; 115 | 116 | for(i=0; i> 4)]; 118 | *ptr++ = hexdig[0x0f & data[i]]; 119 | if ((i & 0x0f) == 0x0f) { 120 | *ptr = '\0'; 121 | ptr = line; 122 | RTMP_Log(level, "%s", line); 123 | } else { 124 | *ptr++ = ' '; 125 | } 126 | } 127 | if (i & 0x0f) { 128 | *ptr = '\0'; 129 | RTMP_Log(level, "%s", line); 130 | } 131 | } 132 | 133 | void RTMP_LogHexString(int level, const uint8_t *data, unsigned long len) 134 | { 135 | #define BP_OFFSET 9 136 | #define BP_GRAPH 60 137 | #define BP_LEN 80 138 | char line[BP_LEN]; 139 | unsigned long i; 140 | 141 | if ( !data || level > RTMP_debuglevel ) 142 | return; 143 | 144 | /* in case len is zero */ 145 | line[0] = '\0'; 146 | 147 | for ( i = 0 ; i < len ; i++ ) { 148 | int n = i % 16; 149 | unsigned off; 150 | 151 | if( !n ) { 152 | if( i ) RTMP_Log( level, "%s", line ); 153 | memset( line, ' ', sizeof(line)-2 ); 154 | line[sizeof(line)-2] = '\0'; 155 | 156 | off = i % 0x0ffffU; 157 | 158 | line[2] = hexdig[0x0f & (off >> 12)]; 159 | line[3] = hexdig[0x0f & (off >> 8)]; 160 | line[4] = hexdig[0x0f & (off >> 4)]; 161 | line[5] = hexdig[0x0f & off]; 162 | line[6] = ':'; 163 | } 164 | 165 | off = BP_OFFSET + n*3 + ((n >= 8)?1:0); 166 | line[off] = hexdig[0x0f & ( data[i] >> 4 )]; 167 | line[off+1] = hexdig[0x0f & data[i]]; 168 | 169 | off = BP_GRAPH + n + ((n >= 8)?1:0); 170 | 171 | if ( isprint( data[i] )) { 172 | line[BP_GRAPH + n] = data[i]; 173 | } else { 174 | line[BP_GRAPH + n] = '.'; 175 | } 176 | } 177 | 178 | RTMP_Log( level, "%s", line ); 179 | } 180 | 181 | /* These should only be used by apps, never by the library itself */ 182 | void RTMP_LogPrintf(const char *format, ...) 183 | { 184 | char str[MAX_PRINT_LEN]=""; 185 | int len; 186 | va_list args; 187 | va_start(args, format); 188 | len = vsnprintf(str, MAX_PRINT_LEN-1, format, args); 189 | va_end(args); 190 | 191 | if ( RTMP_debuglevel==RTMP_LOGCRIT ) 192 | return; 193 | 194 | if ( !fmsg ) fmsg = stderr; 195 | 196 | if (neednl) { 197 | putc('\n', fmsg); 198 | neednl = 0; 199 | } 200 | 201 | if (len > MAX_PRINT_LEN-1) 202 | len = MAX_PRINT_LEN-1; 203 | fprintf(fmsg, "%s", str); 204 | if (str[len-1] == '\n') 205 | fflush(fmsg); 206 | } 207 | 208 | void RTMP_LogStatus(const char *format, ...) 209 | { 210 | char str[MAX_PRINT_LEN]=""; 211 | va_list args; 212 | va_start(args, format); 213 | vsnprintf(str, MAX_PRINT_LEN-1, format, args); 214 | va_end(args); 215 | 216 | if ( RTMP_debuglevel==RTMP_LOGCRIT ) 217 | return; 218 | 219 | if ( !fmsg ) fmsg = stderr; 220 | 221 | fprintf(fmsg, "%s", str); 222 | fflush(fmsg); 223 | neednl = 1; 224 | } 225 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2009 Andrej Stepanchuk 3 | * Copyright (C) 2009-2010 Howard Chu 4 | * 5 | * This file is part of librtmp. 6 | * 7 | * librtmp is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1, 10 | * or (at your option) any later version. 11 | * 12 | * librtmp is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with librtmp see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | * Boston, MA 02110-1301, USA. 21 | * http://www.gnu.org/copyleft/lgpl.html 22 | */ 23 | 24 | #ifndef __RTMP_LOG_H__ 25 | #define __RTMP_LOG_H__ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | /* Enable this to get full debugging output */ 35 | /* #define _DEBUG */ 36 | 37 | #ifdef _DEBUG 38 | #undef NODEBUG 39 | #endif 40 | 41 | typedef enum 42 | { RTMP_LOGCRIT=0, RTMP_LOGERROR, RTMP_LOGWARNING, RTMP_LOGINFO, 43 | RTMP_LOGDEBUG, RTMP_LOGDEBUG2, RTMP_LOGALL 44 | } RTMP_LogLevel; 45 | 46 | extern RTMP_LogLevel RTMP_debuglevel; 47 | 48 | typedef void (RTMP_LogCallback)(int level, const char *fmt, va_list); 49 | void RTMP_LogSetCallback(RTMP_LogCallback *cb); 50 | void RTMP_LogSetOutput(FILE *file); 51 | #ifdef __GNUC__ 52 | void RTMP_LogPrintf(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2))); 53 | void RTMP_LogStatus(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2))); 54 | void RTMP_Log(int level, const char *format, ...) __attribute__ ((__format__ (__printf__, 2, 3))); 55 | #else 56 | void RTMP_LogPrintf(const char *format, ...); 57 | void RTMP_LogStatus(const char *format, ...); 58 | void RTMP_Log(int level, const char *format, ...); 59 | #endif 60 | void RTMP_LogHex(int level, const uint8_t *data, unsigned long len); 61 | void RTMP_LogHexString(int level, const uint8_t *data, unsigned long len); 62 | void RTMP_LogSetLevel(RTMP_LogLevel lvl); 63 | RTMP_LogLevel RTMP_LogGetLevel(void); 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/parseurl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 Andrej Stepanchuk 3 | * Copyright (C) 2009-2010 Howard Chu 4 | * 5 | * This file is part of librtmp. 6 | * 7 | * librtmp is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1, 10 | * or (at your option) any later version. 11 | * 12 | * librtmp is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with librtmp see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | * Boston, MA 02110-1301, USA. 21 | * http://www.gnu.org/copyleft/lgpl.html 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "rtmp_sys.h" 31 | #include "log.h" 32 | 33 | int RTMP_ParseURL(const char *url, int *protocol, AVal *host, unsigned int *port, 34 | AVal *playpath, AVal *app) 35 | { 36 | char *p, *end, *col, *ques, *slash; 37 | 38 | RTMP_Log(RTMP_LOGDEBUG, "Parsing..."); 39 | 40 | *protocol = RTMP_PROTOCOL_RTMP; 41 | *port = 0; 42 | playpath->av_len = 0; 43 | playpath->av_val = NULL; 44 | app->av_len = 0; 45 | app->av_val = NULL; 46 | 47 | /* Old School Parsing */ 48 | 49 | /* look for usual :// pattern */ 50 | p = strstr(url, "://"); 51 | if(!p) { 52 | RTMP_Log(RTMP_LOGERROR, "RTMP URL: No :// in url!"); 53 | return FALSE; 54 | } 55 | { 56 | int len = (int)(p-url); 57 | 58 | if(len == 4 && strncasecmp(url, "rtmp", 4)==0) 59 | *protocol = RTMP_PROTOCOL_RTMP; 60 | else if(len == 5 && strncasecmp(url, "rtmpt", 5)==0) 61 | *protocol = RTMP_PROTOCOL_RTMPT; 62 | else if(len == 5 && strncasecmp(url, "rtmps", 5)==0) 63 | *protocol = RTMP_PROTOCOL_RTMPS; 64 | else if(len == 5 && strncasecmp(url, "rtmpe", 5)==0) 65 | *protocol = RTMP_PROTOCOL_RTMPE; 66 | else if(len == 5 && strncasecmp(url, "rtmfp", 5)==0) 67 | *protocol = RTMP_PROTOCOL_RTMFP; 68 | else if(len == 6 && strncasecmp(url, "rtmpte", 6)==0) 69 | *protocol = RTMP_PROTOCOL_RTMPTE; 70 | else if(len == 6 && strncasecmp(url, "rtmpts", 6)==0) 71 | *protocol = RTMP_PROTOCOL_RTMPTS; 72 | else { 73 | RTMP_Log(RTMP_LOGWARNING, "Unknown protocol!\n"); 74 | goto parsehost; 75 | } 76 | } 77 | 78 | RTMP_Log(RTMP_LOGDEBUG, "Parsed protocol: %d", *protocol); 79 | 80 | parsehost: 81 | /* let's get the hostname */ 82 | p+=3; 83 | 84 | /* check for sudden death */ 85 | if(*p==0) { 86 | RTMP_Log(RTMP_LOGWARNING, "No hostname in URL!"); 87 | return FALSE; 88 | } 89 | 90 | end = p + strlen(p); 91 | col = strchr(p, ':'); 92 | ques = strchr(p, '?'); 93 | slash = strchr(p, '/'); 94 | 95 | { 96 | int hostlen; 97 | if(slash) 98 | hostlen = slash - p; 99 | else 100 | hostlen = end - p; 101 | if(col && col -p < hostlen) 102 | hostlen = col - p; 103 | 104 | if(hostlen < 256) { 105 | host->av_val = p; 106 | host->av_len = hostlen; 107 | RTMP_Log(RTMP_LOGDEBUG, "Parsed host : %.*s", hostlen, host->av_val); 108 | } else { 109 | RTMP_Log(RTMP_LOGWARNING, "Hostname exceeds 255 characters!"); 110 | } 111 | 112 | p+=hostlen; 113 | } 114 | 115 | /* get the port number if available */ 116 | if(*p == ':') { 117 | unsigned int p2; 118 | p++; 119 | p2 = atoi(p); 120 | if(p2 > 65535) { 121 | RTMP_Log(RTMP_LOGWARNING, "Invalid port number!"); 122 | } else { 123 | *port = p2; 124 | } 125 | } 126 | 127 | if(!slash) { 128 | RTMP_Log(RTMP_LOGWARNING, "No application or playpath in URL!"); 129 | return TRUE; 130 | } 131 | p = slash+1; 132 | 133 | { 134 | /* parse application 135 | * 136 | * rtmp://host[:port]/app[/appinstance][/...] 137 | * application = app[/appinstance] 138 | */ 139 | 140 | char *slash2, *slash3 = NULL, *slash4 = NULL; 141 | int applen, appnamelen; 142 | 143 | slash2 = strchr(p, '/'); 144 | if(slash2) 145 | slash3 = strchr(slash2+1, '/'); 146 | if(slash3) 147 | slash4 = strchr(slash3+1, '/'); 148 | 149 | applen = end-p; /* ondemand, pass all parameters as app */ 150 | appnamelen = applen; /* ondemand length */ 151 | 152 | if(ques && strstr(p, "slist=")) { /* whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist= */ 153 | appnamelen = ques-p; 154 | } 155 | else if(strncmp(p, "ondemand/", 9)==0) { 156 | /* app = ondemand/foobar, only pass app=ondemand */ 157 | applen = 8; 158 | appnamelen = 8; 159 | } 160 | else { /* app!=ondemand, so app is app[/appinstance] */ 161 | if(slash4) 162 | appnamelen = slash4-p; 163 | else if(slash3) 164 | appnamelen = slash3-p; 165 | else if(slash2) 166 | appnamelen = slash2-p; 167 | 168 | applen = appnamelen; 169 | } 170 | 171 | app->av_val = p; 172 | app->av_len = applen; 173 | RTMP_Log(RTMP_LOGDEBUG, "Parsed app : %.*s", applen, p); 174 | 175 | p += appnamelen; 176 | } 177 | 178 | if (*p == '/') 179 | p++; 180 | 181 | if (end-p) { 182 | AVal av = {p, end-p}; 183 | RTMP_ParsePlaypath(&av, playpath); 184 | } 185 | 186 | return TRUE; 187 | } 188 | 189 | /* 190 | * Extracts playpath from RTMP URL. playpath is the file part of the 191 | * URL, i.e. the part that comes after rtmp://host:port/app/ 192 | * 193 | * Returns the stream name in a format understood by FMS. The name is 194 | * the playpath part of the URL with formatting depending on the stream 195 | * type: 196 | * 197 | * mp4 streams: prepend "mp4:", remove extension 198 | * mp3 streams: prepend "mp3:", remove extension 199 | * flv streams: remove extension 200 | */ 201 | void RTMP_ParsePlaypath(AVal *in, AVal *out) { 202 | int addMP4 = 0; 203 | int addMP3 = 0; 204 | int subExt = 0; 205 | const char *playpath = in->av_val; 206 | const char *temp, *q, *ext = NULL; 207 | const char *ppstart = playpath; 208 | char *streamname, *destptr, *p; 209 | 210 | int pplen = in->av_len; 211 | 212 | out->av_val = NULL; 213 | out->av_len = 0; 214 | 215 | if ((*ppstart == '?') && 216 | (temp=strstr(ppstart, "slist=")) != 0) { 217 | ppstart = temp+6; 218 | pplen = strlen(ppstart); 219 | 220 | temp = strchr(ppstart, '&'); 221 | if (temp) { 222 | pplen = temp-ppstart; 223 | } 224 | } 225 | 226 | q = strchr(ppstart, '?'); 227 | if (pplen >= 4) { 228 | if (q) 229 | ext = q-4; 230 | else 231 | ext = &ppstart[pplen-4]; 232 | if ((strncmp(ext, ".f4v", 4) == 0) || 233 | (strncmp(ext, ".mp4", 4) == 0)) { 234 | addMP4 = 1; 235 | subExt = 1; 236 | /* Only remove .flv from rtmp URL, not slist params */ 237 | } else if ((ppstart == playpath) && 238 | (strncmp(ext, ".flv", 4) == 0)) { 239 | subExt = 1; 240 | } else if (strncmp(ext, ".mp3", 4) == 0) { 241 | addMP3 = 1; 242 | subExt = 1; 243 | } 244 | } 245 | 246 | streamname = (char *)malloc((pplen+4+1)*sizeof(char)); 247 | if (!streamname) 248 | return; 249 | 250 | destptr = streamname; 251 | if (addMP4) { 252 | if (strncmp(ppstart, "mp4:", 4)) { 253 | strcpy(destptr, "mp4:"); 254 | destptr += 4; 255 | } else { 256 | subExt = 0; 257 | } 258 | } else if (addMP3) { 259 | if (strncmp(ppstart, "mp3:", 4)) { 260 | strcpy(destptr, "mp3:"); 261 | destptr += 4; 262 | } else { 263 | subExt = 0; 264 | } 265 | } 266 | 267 | for (p=(char *)ppstart; pplen >0;) { 268 | /* skip extension */ 269 | if (subExt && p == ext) { 270 | p += 4; 271 | pplen -= 4; 272 | continue; 273 | } 274 | if (*p == '%') { 275 | unsigned int c; 276 | sscanf(p+1, "%02x", &c); 277 | *destptr++ = c; 278 | pplen -= 3; 279 | p += 3; 280 | } else { 281 | *destptr++ = *p++; 282 | pplen--; 283 | } 284 | } 285 | *destptr = '\0'; 286 | 287 | out->av_val = streamname; 288 | out->av_len = destptr - streamname; 289 | } 290 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/rtmp.h: -------------------------------------------------------------------------------- 1 | #ifndef __RTMP_H__ 2 | #define __RTMP_H__ 3 | /* 4 | * Copyright (C) 2005-2008 Team XBMC 5 | * http://www.xbmc.org 6 | * Copyright (C) 2008-2009 Andrej Stepanchuk 7 | * Copyright (C) 2009-2010 Howard Chu 8 | * 9 | * This file is part of librtmp. 10 | * 11 | * librtmp is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU Lesser General Public License as 13 | * published by the Free Software Foundation; either version 2.1, 14 | * or (at your option) any later version. 15 | * 16 | * librtmp is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Lesser General Public License 22 | * along with librtmp see the file COPYING. If not, write to 23 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 24 | * Boston, MA 02110-1301, USA. 25 | * http://www.gnu.org/copyleft/lgpl.html 26 | */ 27 | 28 | #if !defined(NO_CRYPTO) && !defined(CRYPTO) 29 | #define CRYPTO 30 | #endif 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include "amf.h" 37 | 38 | #ifdef __cplusplus 39 | extern "C" 40 | { 41 | #endif 42 | 43 | #define RTMP_LIB_VERSION 0x020300 /* 2.3 */ 44 | 45 | #define RTMP_FEATURE_HTTP 0x01 46 | #define RTMP_FEATURE_ENC 0x02 47 | #define RTMP_FEATURE_SSL 0x04 48 | #define RTMP_FEATURE_MFP 0x08 /* not yet supported */ 49 | #define RTMP_FEATURE_WRITE 0x10 /* publish, not play */ 50 | #define RTMP_FEATURE_HTTP2 0x20 /* server-side rtmpt */ 51 | 52 | #define RTMP_PROTOCOL_UNDEFINED -1 53 | #define RTMP_PROTOCOL_RTMP 0 54 | #define RTMP_PROTOCOL_RTMPE RTMP_FEATURE_ENC 55 | #define RTMP_PROTOCOL_RTMPT RTMP_FEATURE_HTTP 56 | #define RTMP_PROTOCOL_RTMPS RTMP_FEATURE_SSL 57 | #define RTMP_PROTOCOL_RTMPTE (RTMP_FEATURE_HTTP|RTMP_FEATURE_ENC) 58 | #define RTMP_PROTOCOL_RTMPTS (RTMP_FEATURE_HTTP|RTMP_FEATURE_SSL) 59 | #define RTMP_PROTOCOL_RTMFP RTMP_FEATURE_MFP 60 | 61 | #define RTMP_DEFAULT_CHUNKSIZE 128 62 | 63 | /* needs to fit largest number of bytes recv() may return */ 64 | #define RTMP_BUFFER_CACHE_SIZE (16*1024) 65 | 66 | #define RTMP_CHANNELS 65600 67 | 68 | extern const char RTMPProtocolStringsLower[][7]; 69 | extern const AVal RTMP_DefaultFlashVer; 70 | extern int RTMP_ctrlC; 71 | 72 | uint32_t RTMP_GetTime(void); 73 | 74 | /* RTMP_PACKET_TYPE_... 0x00 */ 75 | #define RTMP_PACKET_TYPE_CHUNK_SIZE 0x01 76 | /* RTMP_PACKET_TYPE_... 0x02 */ 77 | #define RTMP_PACKET_TYPE_BYTES_READ_REPORT 0x03 78 | #define RTMP_PACKET_TYPE_CONTROL 0x04 79 | #define RTMP_PACKET_TYPE_SERVER_BW 0x05 80 | #define RTMP_PACKET_TYPE_CLIENT_BW 0x06 81 | /* RTMP_PACKET_TYPE_... 0x07 */ 82 | #define RTMP_PACKET_TYPE_AUDIO 0x08 83 | #define RTMP_PACKET_TYPE_VIDEO 0x09 84 | /* RTMP_PACKET_TYPE_... 0x0A */ 85 | /* RTMP_PACKET_TYPE_... 0x0B */ 86 | /* RTMP_PACKET_TYPE_... 0x0C */ 87 | /* RTMP_PACKET_TYPE_... 0x0D */ 88 | /* RTMP_PACKET_TYPE_... 0x0E */ 89 | #define RTMP_PACKET_TYPE_FLEX_STREAM_SEND 0x0F 90 | #define RTMP_PACKET_TYPE_FLEX_SHARED_OBJECT 0x10 91 | #define RTMP_PACKET_TYPE_FLEX_MESSAGE 0x11 92 | #define RTMP_PACKET_TYPE_INFO 0x12 93 | #define RTMP_PACKET_TYPE_SHARED_OBJECT 0x13 94 | #define RTMP_PACKET_TYPE_INVOKE 0x14 95 | /* RTMP_PACKET_TYPE_... 0x15 */ 96 | #define RTMP_PACKET_TYPE_FLASH_VIDEO 0x16 97 | 98 | #define RTMP_MAX_HEADER_SIZE 18 99 | 100 | #define RTMP_PACKET_SIZE_LARGE 0 101 | #define RTMP_PACKET_SIZE_MEDIUM 1 102 | #define RTMP_PACKET_SIZE_SMALL 2 103 | #define RTMP_PACKET_SIZE_MINIMUM 3 104 | 105 | typedef struct RTMPChunk { 106 | int c_headerSize; 107 | int c_chunkSize; 108 | char *c_chunk; 109 | char c_header[RTMP_MAX_HEADER_SIZE]; 110 | } RTMPChunk; 111 | 112 | typedef struct RTMPPacket { 113 | uint8_t m_headerType; 114 | uint8_t m_packetType; 115 | uint8_t m_hasAbsTimestamp; /* timestamp absolute or relative? */ 116 | int m_nChannel; 117 | uint32_t m_nTimeStamp; /* timestamp */ 118 | int32_t m_nInfoField2; /* last 4 bytes in a long header */ 119 | uint32_t m_nBodySize; 120 | uint32_t m_nBytesRead; 121 | RTMPChunk *m_chunk; 122 | char *m_body; 123 | } RTMPPacket; 124 | 125 | typedef struct RTMPSockBuf { 126 | int sb_socket; 127 | int sb_size; /* number of unprocessed bytes in buffer */ 128 | char *sb_start; /* pointer into sb_pBuffer of next byte to process */ 129 | char sb_buf[RTMP_BUFFER_CACHE_SIZE]; /* data read from socket */ 130 | int sb_timedout; 131 | void *sb_ssl; 132 | } RTMPSockBuf; 133 | 134 | void RTMPPacket_Reset(RTMPPacket *p); 135 | 136 | void RTMPPacket_Dump(RTMPPacket *p); 137 | 138 | int RTMPPacket_Alloc(RTMPPacket *p, uint32_t nSize); 139 | 140 | void RTMPPacket_Free(RTMPPacket *p); 141 | 142 | #define RTMPPacket_IsReady(a) ((a)->m_nBytesRead == (a)->m_nBodySize) 143 | 144 | typedef struct RTMP_LNK { 145 | AVal hostname; 146 | AVal sockshost; 147 | 148 | AVal playpath0; /* parsed from URL */ 149 | AVal playpath; /* passed in explicitly */ 150 | AVal tcUrl; 151 | AVal swfUrl; 152 | AVal pageUrl; 153 | AVal app; 154 | AVal auth; 155 | AVal flashVer; 156 | AVal subscribepath; 157 | AVal usherToken; 158 | AVal token; 159 | AVal pubUser; 160 | AVal pubPasswd; 161 | AMFObject extras; 162 | int edepth; 163 | 164 | int seekTime; 165 | int stopTime; 166 | 167 | #define RTMP_LF_AUTH 0x0001 /* using auth param */ 168 | #define RTMP_LF_LIVE 0x0002 /* stream is live */ 169 | #define RTMP_LF_SWFV 0x0004 /* do SWF verification */ 170 | #define RTMP_LF_PLST 0x0008 /* send playlist before play */ 171 | #define RTMP_LF_BUFX 0x0010 /* toggle stream on BufferEmpty msg */ 172 | #define RTMP_LF_FTCU 0x0020 /* free tcUrl on close */ 173 | #define RTMP_LF_FAPU 0x0040 /* free app on close */ 174 | int lFlags; 175 | 176 | int swfAge; 177 | 178 | int protocol; 179 | int timeout; /* connection timeout in seconds */ 180 | 181 | int pFlags; /* unused, but kept to avoid breaking ABI */ 182 | 183 | unsigned short socksport; 184 | unsigned short port; 185 | 186 | #ifdef CRYPTO 187 | #define RTMP_SWF_HASHLEN 32 188 | void *dh; /* for encryption */ 189 | void *rc4keyIn; 190 | void *rc4keyOut; 191 | 192 | uint32_t SWFSize; 193 | uint8_t SWFHash[RTMP_SWF_HASHLEN]; 194 | char SWFVerificationResponse[RTMP_SWF_HASHLEN+10]; 195 | #endif 196 | } RTMP_LNK; 197 | 198 | /* state for read() wrapper */ 199 | typedef struct RTMP_READ { 200 | char *buf; 201 | char *bufpos; 202 | unsigned int buflen; 203 | uint32_t timestamp; 204 | uint8_t dataType; 205 | uint8_t flags; 206 | #define RTMP_READ_HEADER 0x01 207 | #define RTMP_READ_RESUME 0x02 208 | #define RTMP_READ_NO_IGNORE 0x04 209 | #define RTMP_READ_GOTKF 0x08 210 | #define RTMP_READ_GOTFLVK 0x10 211 | #define RTMP_READ_SEEKING 0x20 212 | int8_t status; 213 | #define RTMP_READ_COMPLETE -3 214 | #define RTMP_READ_ERROR -2 215 | #define RTMP_READ_EOF -1 216 | #define RTMP_READ_IGNORE 0 217 | 218 | /* if bResume == TRUE */ 219 | uint8_t initialFrameType; 220 | uint32_t nResumeTS; 221 | char *metaHeader; 222 | char *initialFrame; 223 | uint32_t nMetaHeaderSize; 224 | uint32_t nInitialFrameSize; 225 | uint32_t nIgnoredFrameCounter; 226 | uint32_t nIgnoredFlvFrameCounter; 227 | } RTMP_READ; 228 | 229 | typedef struct RTMP_METHOD { 230 | AVal name; 231 | int num; 232 | } RTMP_METHOD; 233 | 234 | typedef struct RTMP { 235 | int m_inChunkSize; 236 | int m_outChunkSize; 237 | int m_nBWCheckCounter; 238 | int m_nBytesIn; 239 | int m_nBytesInSent; 240 | int m_nBufferMS; 241 | int m_stream_id; /* returned in _result from createStream */ 242 | int m_mediaChannel; 243 | uint32_t m_mediaStamp; 244 | uint32_t m_pauseStamp; 245 | int m_pausing; 246 | int m_nServerBW; 247 | int m_nClientBW; 248 | uint8_t m_nClientBW2; 249 | uint8_t m_bPlaying; 250 | uint8_t m_bSendEncoding; 251 | uint8_t m_bSendCounter; 252 | 253 | int m_numInvokes; 254 | int m_numCalls; 255 | RTMP_METHOD *m_methodCalls; /* remote method calls queue */ 256 | 257 | int m_channelsAllocatedIn; 258 | int m_channelsAllocatedOut; 259 | RTMPPacket **m_vecChannelsIn; 260 | RTMPPacket **m_vecChannelsOut; 261 | int *m_channelTimestamp; /* abs timestamp of last packet */ 262 | 263 | double m_fAudioCodecs; /* audioCodecs for the connect packet */ 264 | double m_fVideoCodecs; /* videoCodecs for the connect packet */ 265 | double m_fEncoding; /* AMF0 or AMF3 */ 266 | 267 | double m_fDuration; /* duration of stream in seconds */ 268 | 269 | int m_msgCounter; /* RTMPT stuff */ 270 | int m_polling; 271 | int m_resplen; 272 | int m_unackd; 273 | AVal m_clientID; 274 | 275 | RTMP_READ m_read; 276 | RTMPPacket m_write; 277 | RTMPSockBuf m_sb; 278 | RTMP_LNK Link; 279 | } RTMP; 280 | 281 | int RTMP_ParseURL(const char *url, int *protocol, AVal *host, 282 | unsigned int *port, AVal *playpath, AVal *app); 283 | 284 | void RTMP_ParsePlaypath(AVal *in, AVal *out); 285 | 286 | void RTMP_SetBufferMS(RTMP *r, int size); 287 | 288 | void RTMP_UpdateBufferMS(RTMP *r); 289 | 290 | int RTMP_SetOpt(RTMP *r, const AVal *opt, AVal *arg); 291 | 292 | int RTMP_SetupURL(RTMP *r, char *url); 293 | 294 | void RTMP_SetupStream(RTMP *r, int protocol, 295 | AVal *hostname, 296 | unsigned int port, 297 | AVal *sockshost, 298 | AVal *playpath, 299 | AVal *tcUrl, 300 | AVal *swfUrl, 301 | AVal *pageUrl, 302 | AVal *app, 303 | AVal *auth, 304 | AVal *swfSHA256Hash, 305 | uint32_t swfSize, 306 | AVal *flashVer, 307 | AVal *subscribepath, 308 | AVal *usherToken, 309 | int dStart, 310 | int dStop, int bLiveStream, long int timeout); 311 | 312 | int RTMP_Connect(RTMP *r, RTMPPacket *cp); 313 | 314 | struct sockaddr; 315 | 316 | int RTMP_Connect0(RTMP *r, struct sockaddr *svc); 317 | 318 | int RTMP_Connect1(RTMP *r, RTMPPacket *cp); 319 | 320 | int RTMP_Serve(RTMP *r); 321 | 322 | int RTMP_TLS_Accept(RTMP *r, void *ctx); 323 | 324 | int RTMP_ReadPacket(RTMP *r, RTMPPacket *packet); 325 | 326 | int RTMP_SendPacket(RTMP *r, RTMPPacket *packet, int queue); 327 | 328 | int RTMP_SendChunk(RTMP *r, RTMPChunk *chunk); 329 | 330 | int RTMP_IsConnected(RTMP *r); 331 | 332 | int RTMP_Socket(RTMP *r); 333 | 334 | int RTMP_IsTimedout(RTMP *r); 335 | 336 | double RTMP_GetDuration(RTMP *r); 337 | 338 | int RTMP_ToggleStream(RTMP *r); 339 | 340 | int RTMP_ConnectStream(RTMP *r, int seekTime); 341 | 342 | int RTMP_ReconnectStream(RTMP *r, int seekTime); 343 | 344 | void RTMP_DeleteStream(RTMP *r); 345 | 346 | int RTMP_GetNextMediaPacket(RTMP *r, RTMPPacket *packet); 347 | 348 | int RTMP_ClientPacket(RTMP *r, RTMPPacket *packet); 349 | 350 | void RTMP_Init(RTMP *r); 351 | 352 | void RTMP_Close(RTMP *r); 353 | 354 | RTMP *RTMP_Alloc(void); 355 | 356 | void RTMP_Free(RTMP *r); 357 | 358 | void RTMP_EnableWrite(RTMP *r); 359 | 360 | void *RTMP_TLS_AllocServerContext(const char *cert, const char *key); 361 | 362 | void RTMP_TLS_FreeServerContext(void *ctx); 363 | 364 | int RTMP_LibVersion(void); 365 | 366 | void RTMP_UserInterrupt(void); /* user typed Ctrl-C */ 367 | 368 | int RTMP_SendCtrl(RTMP *r, short nType, unsigned int nObject, 369 | unsigned int nTime); 370 | 371 | /* caller probably doesn't know current timestamp, should 372 | * just use RTMP_Pause instead 373 | */ 374 | int RTMP_SendPause(RTMP *r, int DoPause, int dTime); 375 | 376 | int RTMP_Pause(RTMP *r, int DoPause); 377 | 378 | int RTMP_FindFirstMatchingProperty(AMFObject *obj, const AVal *name, 379 | AMFObjectProperty *p); 380 | 381 | int RTMPSockBuf_Fill(RTMPSockBuf *sb); 382 | 383 | int RTMPSockBuf_Send(RTMPSockBuf *sb, const char *buf, int len); 384 | 385 | int RTMPSockBuf_Close(RTMPSockBuf *sb); 386 | 387 | int RTMP_SendCreateStream(RTMP *r); 388 | 389 | int RTMP_SendSeek(RTMP *r, int dTime); 390 | 391 | int RTMP_SendServerBW(RTMP *r); 392 | 393 | int RTMP_SendClientBW(RTMP *r); 394 | 395 | void RTMP_DropRequest(RTMP *r, int i, int freeit); 396 | 397 | int RTMP_Read(RTMP *r, char *buf, int size); 398 | 399 | int RTMP_Write(RTMP *r, const char *buf, int size); 400 | 401 | /* hashswf.c */ 402 | int RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, 403 | int age); 404 | 405 | #ifdef __cplusplus 406 | }; 407 | #endif 408 | 409 | #endif 410 | -------------------------------------------------------------------------------- /app/src/main/cpp/librtmp/rtmp_sys.h: -------------------------------------------------------------------------------- 1 | #ifndef __RTMP_SYS_H__ 2 | #define __RTMP_SYS_H__ 3 | /* 4 | * Copyright (C) 2010 Howard Chu 5 | * 6 | * This file is part of librtmp. 7 | * 8 | * librtmp is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as 10 | * published by the Free Software Foundation; either version 2.1, 11 | * or (at your option) any later version. 12 | * 13 | * librtmp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with librtmp see the file COPYING. If not, write to 20 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 | * Boston, MA 02110-1301, USA. 22 | * http://www.gnu.org/copyleft/lgpl.html 23 | */ 24 | 25 | #ifdef _WIN32 26 | 27 | #include 28 | #include 29 | 30 | #ifdef _MSC_VER /* MSVC */ 31 | #define snprintf _snprintf 32 | #define strcasecmp stricmp 33 | #define strncasecmp strnicmp 34 | #define vsnprintf _vsnprintf 35 | #endif 36 | 37 | #define GetSockError() WSAGetLastError() 38 | #define SetSockError(e) WSASetLastError(e) 39 | #define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e) 40 | #define EWOULDBLOCK WSAETIMEDOUT /* we don't use nonblocking, but we do use timeouts */ 41 | #define sleep(n) Sleep(n*1000) 42 | #define msleep(n) Sleep(n) 43 | #define SET_RCVTIMEO(tv,s) int tv = s*1000 44 | #else /* !_WIN32 */ 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #define GetSockError() errno 54 | #define SetSockError(e) errno = e 55 | #undef closesocket 56 | #define closesocket(s) close(s) 57 | #define msleep(n) usleep(n*1000) 58 | #define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0} 59 | #endif 60 | 61 | #include "rtmp.h" 62 | 63 | #ifdef USE_POLARSSL 64 | #include 65 | #include 66 | #include 67 | #include 68 | #if POLARSSL_VERSION_NUMBER < 0x01010000 69 | #define havege_random havege_rand 70 | #endif 71 | #if POLARSSL_VERSION_NUMBER >= 0x01020000 72 | #define SSL_SET_SESSION(S,resume,timeout,ctx) ssl_set_session(S,ctx) 73 | #else 74 | #define SSL_SET_SESSION(S,resume,timeout,ctx) ssl_set_session(S,resume,timeout,ctx) 75 | #endif 76 | typedef struct tls_ctx { 77 | havege_state hs; 78 | ssl_session ssn; 79 | } tls_ctx; 80 | typedef struct tls_server_ctx { 81 | havege_state *hs; 82 | x509_cert cert; 83 | rsa_context key; 84 | ssl_session ssn; 85 | const char *dhm_P, *dhm_G; 86 | } tls_server_ctx; 87 | 88 | #define TLS_CTX tls_ctx * 89 | #define TLS_client(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\ 90 | ssl_set_endpoint(s, SSL_IS_CLIENT); ssl_set_authmode(s, SSL_VERIFY_NONE);\ 91 | ssl_set_rng(s, havege_random, &ctx->hs);\ 92 | ssl_set_ciphersuites(s, ssl_default_ciphersuites);\ 93 | SSL_SET_SESSION(s, 1, 600, &ctx->ssn) 94 | #define TLS_server(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\ 95 | ssl_set_endpoint(s, SSL_IS_SERVER); ssl_set_authmode(s, SSL_VERIFY_NONE);\ 96 | ssl_set_rng(s, havege_random, ((tls_server_ctx*)ctx)->hs);\ 97 | ssl_set_ciphersuites(s, ssl_default_ciphersuites);\ 98 | SSL_SET_SESSION(s, 1, 600, &((tls_server_ctx*)ctx)->ssn);\ 99 | ssl_set_own_cert(s, &((tls_server_ctx*)ctx)->cert, &((tls_server_ctx*)ctx)->key);\ 100 | ssl_set_dh_param(s, ((tls_server_ctx*)ctx)->dhm_P, ((tls_server_ctx*)ctx)->dhm_G) 101 | #define TLS_setfd(s,fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd) 102 | #define TLS_connect(s) ssl_handshake(s) 103 | #define TLS_accept(s) ssl_handshake(s) 104 | #define TLS_read(s,b,l) ssl_read(s,(unsigned char *)b,l) 105 | #define TLS_write(s,b,l) ssl_write(s,(unsigned char *)b,l) 106 | #define TLS_shutdown(s) ssl_close_notify(s) 107 | #define TLS_close(s) ssl_free(s); free(s) 108 | 109 | #elif defined(USE_GNUTLS) 110 | #include 111 | typedef struct tls_ctx { 112 | gnutls_certificate_credentials_t cred; 113 | gnutls_priority_t prios; 114 | } tls_ctx; 115 | #define TLS_CTX tls_ctx * 116 | #define TLS_client(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_CLIENT); gnutls_priority_set(s, ctx->prios); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx->cred) 117 | #define TLS_server(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_SERVER); gnutls_priority_set_direct(s, "NORMAL", NULL); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx) 118 | #define TLS_setfd(s,fd) gnutls_transport_set_ptr(s, (gnutls_transport_ptr_t)(long)fd) 119 | #define TLS_connect(s) gnutls_handshake(s) 120 | #define TLS_accept(s) gnutls_handshake(s) 121 | #define TLS_read(s,b,l) gnutls_record_recv(s,b,l) 122 | #define TLS_write(s,b,l) gnutls_record_send(s,b,l) 123 | #define TLS_shutdown(s) gnutls_bye(s, GNUTLS_SHUT_RDWR) 124 | #define TLS_close(s) gnutls_deinit(s) 125 | 126 | #else /* USE_OPENSSL */ 127 | #define TLS_CTX SSL_CTX * 128 | #define TLS_client(ctx,s) s = SSL_new(ctx) 129 | #define TLS_server(ctx,s) s = SSL_new(ctx) 130 | #define TLS_setfd(s,fd) SSL_set_fd(s,fd) 131 | #define TLS_connect(s) SSL_connect(s) 132 | #define TLS_accept(s) SSL_accept(s) 133 | #define TLS_read(s,b,l) SSL_read(s,b,l) 134 | #define TLS_write(s,b,l) SSL_write(s,b,l) 135 | #define TLS_shutdown(s) SSL_shutdown(s) 136 | #define TLS_close(s) SSL_free(s) 137 | 138 | #endif 139 | #endif 140 | -------------------------------------------------------------------------------- /app/src/main/cpp/native-lib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "packt.h" 3 | 4 | 5 | Pusher *pusher = 0; 6 | 7 | JNIEXPORT jboolean JNICALL 8 | Java_com_dongnao_screencapture_RtmpManager_connect(JNIEnv *env, jobject instance, jstring url_) { 9 | const char *url = (*env)->GetStringUTFChars(env, url_, 0); 10 | int ret; 11 | do { 12 | pusher = malloc(sizeof(Pusher)); 13 | memset(pusher, 0, sizeof(Pusher)); 14 | pusher->rtmp = RTMP_Alloc(); 15 | RTMP_Init(pusher->rtmp); 16 | pusher->rtmp->Link.timeout = 10; 17 | LOGI("connect %s", url); 18 | if (!(ret = RTMP_SetupURL(pusher->rtmp, url))) break; 19 | RTMP_EnableWrite(pusher->rtmp); 20 | LOGI("RTMP_Connect"); 21 | if (!(ret = RTMP_Connect(pusher->rtmp, 0))) break; 22 | LOGI("RTMP_ConnectStream "); 23 | if (!(ret = RTMP_ConnectStream(pusher->rtmp, 0))) break; 24 | LOGI("connect success"); 25 | } while (0); 26 | (*env)->ReleaseStringUTFChars(env, url_, url); 27 | return ret; 28 | } 29 | 30 | JNIEXPORT jboolean JNICALL 31 | Java_com_dongnao_screencapture_RtmpManager_isConnect(JNIEnv *env, jobject instance) { 32 | return pusher && pusher->rtmp && RTMP_IsConnected(pusher->rtmp); 33 | } 34 | 35 | JNIEXPORT void JNICALL 36 | Java_com_dongnao_screencapture_RtmpManager_disConnect(JNIEnv *env, jobject instance) { 37 | if (pusher) { 38 | if (pusher->sps) { 39 | free(pusher->sps); 40 | } 41 | if (pusher->pps) { 42 | free(pusher->pps); 43 | } 44 | if (pusher->rtmp) { 45 | RTMP_Close(pusher->rtmp); 46 | RTMP_Free(pusher->rtmp); 47 | } 48 | free(pusher); 49 | pusher = 0; 50 | } 51 | } 52 | 53 | int sendPacket(RTMPPacket *packet) { 54 | int r = RTMP_SendPacket(pusher->rtmp, packet, 1); 55 | RTMPPacket_Free(packet); 56 | free(packet); 57 | return r; 58 | } 59 | 60 | int sendVideo(char *buf, int len, long tms) { 61 | int ret; 62 | do { 63 | if (buf[4] == 0x67) {//sps pps 64 | if (pusher && (!pusher->pps || !pusher->sps)) { 65 | parseVideoConfiguration(buf, len, pusher); 66 | } 67 | } else { 68 | if (buf[4] == 0x65) {//关键帧 69 | RTMPPacket *packet = packetVideoDecode(pusher); 70 | if (!(ret = sendPacket(packet))) { 71 | break; 72 | } 73 | } 74 | RTMPPacket *packet = packetVideoData(buf, len, tms, pusher); 75 | ret = sendPacket(packet); 76 | } 77 | } while (0); 78 | return ret; 79 | } 80 | 81 | int sendAudio(char *buf, int len, int type, int tms) { 82 | int ret; 83 | do { 84 | RTMPPacket *packet = packetAudioData(buf, len, type, tms, pusher); 85 | ret = sendPacket(packet); 86 | } while (0); 87 | return ret; 88 | } 89 | 90 | JNIEXPORT jboolean JNICALL 91 | Java_com_dongnao_screencapture_RtmpManager_sendData(JNIEnv *env, jobject instance, jbyteArray data_, 92 | jint len, jint type, jlong tms) { 93 | jbyte *data = (*env)->GetByteArrayElements(env, data_, NULL); 94 | int ret; 95 | switch (type) { 96 | case 0: //video 97 | ret = sendVideo(data, 】len, tms); 98 | break; 99 | default: //audio 100 | ret = sendAudio(data, len, type, tms); 101 | break; 102 | } 103 | (*env)->ReleaseByteArrayElements(env, data_, data, 0); 104 | return ret; 105 | } -------------------------------------------------------------------------------- /app/src/main/cpp/packt.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by liuxiang on 2017/9/14. 3 | // 4 | 5 | #ifndef SCREENLIVE_PACKT_H 6 | #define SCREENLIVE_PACKT_H 7 | 8 | 9 | #include 10 | #include "librtmp/rtmp.h" 11 | #include 12 | #include 13 | 14 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,"RTMP",__VA_ARGS__) 15 | 16 | typedef struct { 17 | int sps_len; 18 | int pps_len; 19 | char *sps; 20 | char *pps; 21 | RTMP *rtmp; 22 | } Pusher; 23 | 24 | 25 | RTMPPacket *packetVideoDecode(Pusher *pusher) { 26 | int body_size = 13 + pusher->sps_len + 3 + pusher->pps_len; 27 | RTMPPacket *packet = (RTMPPacket *) malloc(sizeof(RTMPPacket)); 28 | RTMPPacket_Alloc(packet, body_size); 29 | int i = 0; 30 | //AVC sequence header 与IDR一样 31 | packet->m_body[i++] = 0x17; 32 | //AVC sequence header 设置为0x00 33 | packet->m_body[i++] = 0x00; 34 | //CompositionTime 35 | packet->m_body[i++] = 0x00; 36 | packet->m_body[i++] = 0x00; 37 | packet->m_body[i++] = 0x00; 38 | //AVC sequence header 39 | packet->m_body[i++] = 0x01; //configurationVersion 版本号 1 40 | packet->m_body[i++] = pusher->sps[1]; //profile 如baseline、main、 high 41 | 42 | packet->m_body[i++] = pusher->sps[2]; //profile_compatibility 兼容性 43 | packet->m_body[i++] = pusher->sps[3]; //profile level 44 | packet->m_body[i++] = 0xFF; // reserved(111111) + lengthSizeMinusOne(2位 nal 长度) 总是0xff 45 | //sps 46 | packet->m_body[i++] = 0xE1; //reserved(111) + lengthSizeMinusOne(5位 sps 个数) 总是0xe1 47 | //sps length 2字节 48 | packet->m_body[i++] = (pusher->sps_len >> 8) & 0xff; //第0个字节 49 | packet->m_body[i++] = pusher->sps_len & 0xff; //第1个字节 50 | memcpy(&packet->m_body[i], pusher->sps, pusher->sps_len); 51 | i += pusher->sps_len; 52 | 53 | /*pps*/ 54 | packet->m_body[i++] = 0x01; //pps number 55 | //pps length 56 | packet->m_body[i++] = (pusher->pps_len >> 8) & 0xff; 57 | packet->m_body[i++] = pusher->pps_len & 0xff; 58 | memcpy(&packet->m_body[i], pusher->pps, pusher->pps_len); 59 | 60 | packet->m_packetType = RTMP_PACKET_TYPE_VIDEO; 61 | packet->m_nBodySize = body_size; 62 | packet->m_nChannel = 0x04; 63 | packet->m_nTimeStamp = 0; 64 | packet->m_hasAbsTimestamp = 0; 65 | packet->m_headerType = RTMP_PACKET_SIZE_LARGE; 66 | packet->m_nInfoField2 = pusher->rtmp->m_stream_id; 67 | return packet; 68 | } 69 | 70 | RTMPPacket *packetVideoData(char *buf, int len, const long tms, Pusher *pusher) { 71 | buf += 4; 72 | len -= 4; 73 | int body_size = len + 9; 74 | RTMPPacket *packet = (RTMPPacket *) malloc(sizeof(RTMPPacket)); 75 | RTMPPacket_Alloc(packet, len + 9); 76 | 77 | packet->m_body[0] = 0x27; 78 | if (buf[0] == 0x65) { //关键帧 79 | packet->m_body[0] = 0x17; 80 | LOGI("发送关键帧 data"); 81 | } 82 | packet->m_body[1] = 0x01; 83 | packet->m_body[2] = 0x00; 84 | packet->m_body[3] = 0x00; 85 | packet->m_body[4] = 0x00; 86 | 87 | //长度 88 | packet->m_body[5] = (len >> 24) & 0xff; 89 | packet->m_body[6] = (len >> 16) & 0xff; 90 | packet->m_body[7] = (len >> 8) & 0xff; 91 | packet->m_body[8] = (len) & 0xff; 92 | 93 | //数据 94 | memcpy(&packet->m_body[9], buf, len); 95 | 96 | 97 | packet->m_packetType = RTMP_PACKET_TYPE_VIDEO; 98 | packet->m_nBodySize = body_size; 99 | packet->m_nChannel = 0x04; 100 | packet->m_nTimeStamp = tms; 101 | packet->m_hasAbsTimestamp = 0; 102 | packet->m_headerType = RTMP_PACKET_SIZE_LARGE; 103 | packet->m_nInfoField2 = pusher->rtmp->m_stream_id; 104 | return packet; 105 | 106 | } 107 | 108 | RTMPPacket *packetAudioData(const char *buf, const int len, const int type, const long tms, 109 | Pusher *pusher) { 110 | int body_size = len + 2; 111 | RTMPPacket *packet = (RTMPPacket *) malloc(sizeof(RTMPPacket)); 112 | RTMPPacket_Alloc(packet, body_size); 113 | //aac的数据头 114 | packet->m_body[0] = 0xAF; 115 | packet->m_body[1] = 0x01; 116 | //解码信息 117 | if (type == 1) { 118 | packet->m_body[1] = 0x00; 119 | } 120 | memcpy(&packet->m_body[2], buf, len); 121 | 122 | packet->m_packetType = RTMP_PACKET_TYPE_AUDIO; 123 | packet->m_nBodySize = body_size; 124 | packet->m_nChannel = 0x05; 125 | packet->m_nTimeStamp = tms; 126 | packet->m_hasAbsTimestamp = 0; 127 | packet->m_headerType = RTMP_PACKET_SIZE_LARGE; 128 | packet->m_nInfoField2 = pusher->rtmp->m_stream_id; 129 | return packet; 130 | } 131 | 132 | 133 | void parseVideoConfiguration(char *data, int len, Pusher *pusher) { 134 | for (int i = 0; i < len; i++) { 135 | //0x00 0x00 0x00 0x01 136 | if (i + 4 < len) { 137 | if (data[i] == 0x00 && data[i + 1] == 0x00 138 | && data[i + 2] == 0x00 139 | && data[i + 3] == 0x01) { 140 | //0x00 0x00 0x00 0x01 7 sps 0x00 0x00 0x00 0x01 8 pps 141 | //将sps pps分开 142 | //找到pps 143 | if ((data[i + 4] & 0x1f) == 8) { 144 | //去掉界定符 145 | pusher->sps_len = i - 4; 146 | pusher->sps = (char *) malloc(sizeof(char) * pusher->sps_len); 147 | memcpy(pusher->sps, data + 4, pusher->sps_len); 148 | pusher->pps_len = len - (4 + pusher->sps_len) - 4; 149 | pusher->pps = (char *) malloc(sizeof(char) * pusher->pps_len); 150 | memcpy(pusher->pps, data + 4 + pusher->sps_len + 4, 151 | pusher->pps_len); 152 | LOGI("sps:%d pps:%d", pusher->sps_len, pusher->pps_len); 153 | break; 154 | } 155 | } 156 | } 157 | } 158 | } 159 | 160 | 161 | #endif //SCREENLIVE_PACKT_H 162 | -------------------------------------------------------------------------------- /app/src/main/java/com/dongnao/screencapture/AudioCodec.java: -------------------------------------------------------------------------------- 1 | package com.dongnao.screencapture; 2 | 3 | import android.media.AudioFormat; 4 | import android.media.AudioRecord; 5 | import android.media.MediaCodec; 6 | import android.media.MediaCodecInfo; 7 | import android.media.MediaFormat; 8 | import android.media.MediaRecorder; 9 | import android.util.Log; 10 | 11 | import java.io.IOException; 12 | import java.nio.ByteBuffer; 13 | import java.util.concurrent.LinkedBlockingQueue; 14 | 15 | /** 16 | * Created by xiang on 2017/9/11. 17 | */ 18 | 19 | public class AudioCodec extends Thread { 20 | 21 | private final static String MIME_TYPE = "audio/mp4a-latm"; 22 | private final static int SAMPLE_RATE = 44100; //采样 23 | private final static int CHANNEL_COUNT = 1; //单声道 24 | private final static int BITRETE = 64_000; 25 | 26 | 27 | private MediaCodec.BufferInfo bufferInfo; 28 | private final static String TAG = "AudioCodec"; 29 | private MediaCodec mediaCodec; 30 | private byte[] audioDecoderSpecificInfo; 31 | private AudioRecord audioRecord; 32 | private boolean isRecoding; 33 | 34 | private long startTime; 35 | 36 | 37 | public boolean prepare() { 38 | bufferInfo = new MediaCodec.BufferInfo(); 39 | MediaFormat format = MediaFormat.createAudioFormat(MIME_TYPE, SAMPLE_RATE, CHANNEL_COUNT); 40 | format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel 41 | .AACObjectLC); 42 | format.setInteger(MediaFormat.KEY_BIT_RATE, BITRETE); 43 | Log.d(TAG, "created audio format: " + format); 44 | try { 45 | mediaCodec = MediaCodec.createEncoderByType(MIME_TYPE); 46 | } catch (IOException e) { 47 | e.printStackTrace(); 48 | return false; 49 | } 50 | mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 51 | mediaCodec.start(); 52 | //从faac库将代码用java实现了. 53 | audioDecoderSpecificInfo = AudioSpecificConfig.getAudioDecoderSpecificInfo 54 | (MediaCodecInfo.CodecProfileLevel 55 | .AACObjectLC, SAMPLE_RATE, CHANNEL_COUNT); 56 | // 这样也能拿到 57 | // ByteBuffer csd0 = mediaCodec.getOutputFormat().getByteBuffer("csd-0"); 58 | int minBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, 59 | AudioFormat.CHANNEL_IN_MONO, 60 | AudioFormat.ENCODING_PCM_16BIT); 61 | audioRecord = new AudioRecord( 62 | MediaRecorder.AudioSource.MIC, SAMPLE_RATE, 63 | AudioFormat.CHANNEL_IN_MONO, 64 | AudioFormat.ENCODING_PCM_16BIT, minBufferSize); 65 | return true; 66 | } 67 | 68 | 69 | @Override 70 | public void run() { 71 | IFrame iFrame = new IFrame(); 72 | iFrame.setBuffer(audioDecoderSpecificInfo); 73 | iFrame.setType(IFrame.RTMP_PACKET_TYPE_AUDIO_HEAD); 74 | RtmpManager.getInstance().addFrame(iFrame); 75 | audioRecord.startRecording(); 76 | byte[] buffer = new byte[2048]; 77 | while (isRecoding) { 78 | int len = audioRecord.read(buffer, 0, buffer.length); 79 | if (len <= 0) { 80 | continue; 81 | } 82 | //立即得到有效输入缓冲区 83 | int index = mediaCodec.dequeueInputBuffer(0); 84 | if (index >= 0) { 85 | ByteBuffer inputBuffer = mediaCodec.getInputBuffer(index); 86 | inputBuffer.clear(); 87 | inputBuffer.put(buffer, 0, len); 88 | //填充数据后再加入队列 89 | mediaCodec.queueInputBuffer(index, 0, len, 90 | System.currentTimeMillis(), 0); 91 | } 92 | index = mediaCodec.dequeueOutputBuffer(bufferInfo, 0); 93 | while (index >= 0 && isRecoding) { 94 | ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(index); 95 | byte[] outData = new byte[bufferInfo.size]; 96 | outputBuffer.get(outData); 97 | 98 | if (startTime == 0) { 99 | startTime = bufferInfo.presentationTimeUs; 100 | Log.i(TAG, "audio tms " + startTime); 101 | } 102 | iFrame = new IFrame(); 103 | iFrame.setBuffer(outData); 104 | iFrame.setType(IFrame.RTMP_PACKET_TYPE_AUDIO_DATA); 105 | iFrame.setTms(bufferInfo.presentationTimeUs - startTime); 106 | RtmpManager.getInstance().addFrame(iFrame); 107 | mediaCodec.releaseOutputBuffer(index, false); 108 | index = mediaCodec.dequeueOutputBuffer(bufferInfo, 0); 109 | } 110 | } 111 | audioRecord.stop(); 112 | audioRecord.release(); 113 | audioRecord = null; 114 | 115 | mediaCodec.stop(); 116 | mediaCodec.release(); 117 | mediaCodec = null; 118 | startTime = 0; 119 | isRecoding = false; 120 | Log.i(TAG, "release audio"); 121 | } 122 | 123 | public void startCoding() { 124 | isRecoding = true; 125 | start(); 126 | } 127 | 128 | public void stopCoding() { 129 | isRecoding = false; 130 | try { 131 | join(); 132 | } catch (InterruptedException e) { 133 | e.printStackTrace(); 134 | } 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /app/src/main/java/com/dongnao/screencapture/AudioSpecificConfig.java: -------------------------------------------------------------------------------- 1 | package com.dongnao.screencapture; 2 | 3 | public class AudioSpecificConfig { 4 | 5 | private final static int BYTE_NUMBIT = 8; 6 | 7 | private static void putByte(AudioTag audioTag, long data, int numBit) { 8 | long bits; 9 | int num = 0; 10 | int maxNum = BYTE_NUMBIT - audioTag.getCurrentBit() % BYTE_NUMBIT; 11 | int curNum = 0; 12 | while (num < numBit) { 13 | curNum = Math.min(numBit - num, maxNum); 14 | bits = data >> (numBit - num - curNum); 15 | WriteByte(audioTag, bits, curNum); 16 | num += curNum; 17 | maxNum = BYTE_NUMBIT; 18 | } 19 | } 20 | 21 | private static void WriteByte(AudioTag audioTag, long data, int numBit) { 22 | long numUsed, idx; 23 | idx = (audioTag.getCurrentBit() / BYTE_NUMBIT) % 2; 24 | numUsed = audioTag.getCurrentBit() % BYTE_NUMBIT; 25 | audioTag.getData()[(int) idx] |= (data & ((1 << numBit) - 1)) << (BYTE_NUMBIT 26 | - numUsed - numBit); 27 | audioTag.addCurrentBit(numBit); 28 | } 29 | 30 | private static int GetSRIndex(int sampleRate) { 31 | 32 | if (92017 <= sampleRate) 33 | return 0; 34 | if (75132 <= sampleRate) 35 | return 1; 36 | if (55426 <= sampleRate) 37 | return 2; 38 | if (46009 <= sampleRate) 39 | return 3; 40 | if (37566 <= sampleRate) 41 | return 4; 42 | if (27713 <= sampleRate) 43 | return 5; 44 | if (23004 <= sampleRate) 45 | return 6; 46 | if (18783 <= sampleRate) 47 | return 7; 48 | if (13856 <= sampleRate) 49 | return 8; 50 | if (11502 <= sampleRate) 51 | return 9; 52 | if (9391 <= sampleRate) 53 | return 10; 54 | 55 | return 11; 56 | } 57 | 58 | public static byte[] getAudioDecoderSpecificInfo(int profile, int sampleRate, int channel) { 59 | // MAIN:1 LOW(LC):2 SSR:3 LTP:4 60 | // 采样率 61 | // 声道 62 | AudioTag audioTag = new AudioTag(); 63 | putByte(audioTag, profile, 5); 64 | putByte(audioTag, GetSRIndex(sampleRate), 4); 65 | putByte(audioTag, channel, 4); 66 | return audioTag.getData(); 67 | } 68 | 69 | private static class AudioTag { 70 | 71 | private byte[] data; 72 | 73 | private int currentBit = 0; 74 | 75 | public AudioTag() { 76 | data = new byte[2]; 77 | } 78 | 79 | public int getCurrentBit() { 80 | return currentBit; 81 | } 82 | 83 | public byte[] getData() { 84 | return data; 85 | } 86 | 87 | public void addCurrentBit(int currentBit) { 88 | this.currentBit += currentBit; 89 | } 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/dongnao/screencapture/IFrame.java: -------------------------------------------------------------------------------- 1 | package com.dongnao.screencapture; 2 | 3 | /** 4 | * Created by xiang on 2017/9/11. 5 | */ 6 | 7 | public class IFrame { 8 | 9 | 10 | public static final int RTMP_PACKET_TYPE_VIDEO = 0; 11 | public static final int RTMP_PACKET_TYPE_AUDIO_HEAD = 1; 12 | public static final int RTMP_PACKET_TYPE_AUDIO_DATA = 2; 13 | 14 | private byte[] buffer; 15 | private int type; 16 | private long tms; 17 | 18 | 19 | public byte[] getBuffer() { 20 | return buffer; 21 | } 22 | 23 | public void setBuffer(byte[] buffer) { 24 | this.buffer = buffer; 25 | } 26 | 27 | public int getType() { 28 | return type; 29 | } 30 | 31 | public void setType(int type) { 32 | this.type = type; 33 | } 34 | 35 | public void setTms(long tms) { 36 | this.tms = tms; 37 | } 38 | 39 | public long getTms() { 40 | return tms; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/dongnao/screencapture/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.dongnao.screencapture; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.content.Intent; 6 | import android.os.Build; 7 | import android.os.Bundle; 8 | import android.view.View; 9 | 10 | 11 | public class MainActivity extends Activity implements RtmpManager.Callback { 12 | 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_main); 18 | RtmpManager.getInstance().setCallback(this); 19 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 20 | requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 10); 21 | } 22 | } 23 | 24 | @Override 25 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 26 | super.onActivityResult(requestCode, resultCode, data); 27 | RtmpManager.getInstance().onActivityResult(requestCode, resultCode, data); 28 | } 29 | 30 | public void stoplive(View view) { 31 | RtmpManager.getInstance().stopScreenCapture(); 32 | } 33 | 34 | public void startlive(View view) { 35 | RtmpManager.getInstance().startScreenCapture(this, "rtmp://192.168.50.109/myapp/test"); 36 | //RtmpManager.getInstance().startScreenCapture(this, "rtmp://send3.douyu 37 | // .com/live/3251491rcWeNgVtN?wsSecret=6b671a7d166273eb3c29eaf6des2kd34&wsTime=59be2dbc 38 | // &wsSeek=off"); 39 | } 40 | 41 | //手游直播、监控操作(安全、分析行为) 42 | @Override 43 | public void onStatus(int status) { 44 | if (status == RtmpManager.STATUS_START) { 45 | 46 | } else { 47 | 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/dongnao/screencapture/RtmpManager.java: -------------------------------------------------------------------------------- 1 | package com.dongnao.screencapture; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.media.projection.MediaProjection; 7 | import android.media.projection.MediaProjectionManager; 8 | import android.os.Handler; 9 | import android.os.Message; 10 | 11 | import java.util.concurrent.LinkedBlockingQueue; 12 | 13 | /** 14 | * Created by xiang on 2017/9/11. 15 | */ 16 | 17 | public class RtmpManager { 18 | 19 | 20 | public static final int STATUS_START = 0; 21 | public static final int STATUS_STOP = 1; 22 | 23 | public static final int STATUS_NO_PREMISSION = -1; 24 | public static final int STATUS_VIDEO_FAIL = -2; 25 | public static final int STATUS_AUDIO_FAIL = -3; 26 | public static final int STATUS_CONNECT_FAIL = -4; 27 | public static final int STATUS_SEND_DATA_FAIL = -5; 28 | 29 | 30 | public interface Callback { 31 | void onStatus(int status); 32 | } 33 | 34 | static { 35 | System.loadLibrary("native-lib"); 36 | } 37 | 38 | private VideoCodec videoCodec; 39 | private AudioCodec audioCodec; 40 | private Callback callback; 41 | private String url; 42 | private LinkedBlockingQueue