winlin

srs-librtmp: implements play stream.

1 -/*  
2 -The MIT License (MIT)  
3 -  
4 -Copyright (c) 2013-2014 winlin  
5 -  
6 -Permission is hereby granted, free of charge, to any person obtaining a copy of  
7 -this software and associated documentation files (the "Software"), to deal in  
8 -the Software without restriction, including without limitation the rights to  
9 -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of  
10 -the Software, and to permit persons to whom the Software is furnished to do so,  
11 -subject to the following conditions:  
12 -  
13 -The above copyright notice and this permission notice shall be included in all  
14 -copies or substantial portions of the Software.  
15 -  
16 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS  
18 -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR  
19 -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER  
20 -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
21 -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
22 -*/  
23 -  
24 -#include <srs_librtmp.hpp>  
25 -  
26 -#include <stdlib.h>  
27 -  
28 -#include <string>  
29 -using namespace std;  
30 -  
31 -#include <srs_kernel_error.hpp>  
32 -#include <srs_protocol_rtmp.hpp>  
33 -#include <srs_lib_simple_socket.hpp>  
34 -#include <srs_kernel_log.hpp>  
35 -#include <srs_protocol_utility.hpp>  
36 -  
37 -// if user want to define log, define the folowing macro.  
38 -#ifndef SRS_RTMP_USER_DEFINED_LOG  
39 - // kernel module.  
40 - ISrsLog* _srs_log = new ISrsLog();  
41 - ISrsThreadContext* _srs_context = new ISrsThreadContext();  
42 -#endif  
43 -  
44 -/**  
45 -* export runtime context.  
46 -*/  
47 -struct Context  
48 -{  
49 - std::string url;  
50 - std::string tcUrl;  
51 - std::string host;  
52 - std::string port;  
53 - std::string vhost;  
54 - std::string app;  
55 - std::string stream;  
56 -  
57 - SrsRtmpClient* rtmp;  
58 - SimpleSocketStream* skt;  
59 - int stream_id;  
60 -  
61 - Context() {  
62 - rtmp = NULL;  
63 - skt = NULL;  
64 - stream_id = 0;  
65 - }  
66 - virtual ~Context() {  
67 - srs_freep(rtmp);  
68 - srs_freep(skt);  
69 - }  
70 -};  
71 -  
72 -int srs_librtmp_context_connect(Context* context)  
73 -{  
74 - int ret = ERROR_SUCCESS;  
75 -  
76 - // parse uri  
77 - size_t pos = string::npos;  
78 - string uri = context->url;  
79 - // tcUrl, stream  
80 - if ((pos = uri.rfind("/")) != string::npos) {  
81 - context->stream = uri.substr(pos + 1);  
82 - context->tcUrl = uri = uri.substr(0, pos);  
83 - }  
84 - // schema  
85 - if ((pos = uri.find("rtmp://")) != string::npos) {  
86 - uri = uri.substr(pos + 7);  
87 - }  
88 - // host/vhost/port  
89 - if ((pos = uri.find(":")) != string::npos) {  
90 - context->vhost = context->host = uri.substr(0, pos);  
91 - uri = uri.substr(pos + 1);  
92 -  
93 - if ((pos = uri.find("/")) != string::npos) {  
94 - context->port = uri.substr(0, pos);  
95 - uri = uri.substr(pos + 1);  
96 - }  
97 - } else {  
98 - if ((pos = uri.find("/")) != string::npos) {  
99 - context->vhost = context->host = uri.substr(0, pos);  
100 - uri = uri.substr(pos + 1);  
101 - }  
102 - context->port = RTMP_DEFAULT_PORT;  
103 - }  
104 - // app  
105 - context->app = uri;  
106 - // query of app  
107 - if ((pos = uri.find("?")) != string::npos) {  
108 - context->app = uri.substr(0, pos);  
109 - string query = uri.substr(pos + 1);  
110 - if ((pos = query.find("vhost=")) != string::npos) {  
111 - context->vhost = query.substr(pos + 6);  
112 - if ((pos = context->vhost.find("&")) != string::npos) {  
113 - context->vhost = context->vhost.substr(pos);  
114 - }  
115 - }  
116 - }  
117 -  
118 - // create socket  
119 - srs_freep(context->skt);  
120 - context->skt = new SimpleSocketStream();  
121 -  
122 - if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) {  
123 - return ret;  
124 - }  
125 -  
126 - // connect to server:port  
127 - string server = srs_dns_resolve(context->host);  
128 - if (server.empty()) {  
129 - return -1;  
130 - }  
131 - if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) {  
132 - return ret;  
133 - }  
134 -  
135 - return ret;  
136 -}  
137 -  
138 -#ifdef __cplusplus  
139 -extern "C"{  
140 -#endif  
141 -  
142 -srs_rtmp_t srs_rtmp_create(const char* url)  
143 -{  
144 - Context* context = new Context();  
145 - context->url = url;  
146 - return context;  
147 -}  
148 -  
149 -void srs_rtmp_destroy(srs_rtmp_t rtmp)  
150 -{  
151 - srs_assert(rtmp != NULL);  
152 - Context* context = (Context*)rtmp;  
153 -  
154 - srs_freep(context);  
155 -}  
156 -  
157 -int srs_simple_handshake(srs_rtmp_t rtmp)  
158 -{  
159 - int ret = ERROR_SUCCESS;  
160 -  
161 - srs_assert(rtmp != NULL);  
162 - Context* context = (Context*)rtmp;  
163 -  
164 - // parse uri, resolve host, connect to server:port  
165 - if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) {  
166 - return ret;  
167 - }  
168 -  
169 - // simple handshake  
170 - srs_freep(context->rtmp);  
171 - context->rtmp = new SrsRtmpClient(context->skt);  
172 -  
173 - if ((ret = context->rtmp->simple_handshake()) != ERROR_SUCCESS) {  
174 - return ret;  
175 - }  
176 -  
177 - return ret;  
178 -}  
179 -  
180 -int srs_complex_handshake(srs_rtmp_t rtmp)  
181 -{  
182 -#ifndef SRS_SSL  
183 - return ERROR_RTMP_HS_SSL_REQUIRE;  
184 -#endif  
185 -  
186 - int ret = ERROR_SUCCESS;  
187 -  
188 - srs_assert(rtmp != NULL);  
189 - Context* context = (Context*)rtmp;  
190 -  
191 - // parse uri, resolve host, connect to server:port  
192 - if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) {  
193 - return ret;  
194 - }  
195 -  
196 - // complex handshake  
197 - srs_freep(context->rtmp);  
198 - context->rtmp = new SrsRtmpClient(context->skt);  
199 -  
200 - if ((ret = context->rtmp->complex_handshake()) != ERROR_SUCCESS) {  
201 - return ret;  
202 - }  
203 -  
204 - return ret;  
205 -}  
206 -  
207 -int srs_connect_app(srs_rtmp_t rtmp)  
208 -{  
209 - int ret = ERROR_SUCCESS;  
210 -  
211 - srs_assert(rtmp != NULL);  
212 - Context* context = (Context*)rtmp;  
213 -  
214 - string tcUrl = "rtmp://";  
215 - tcUrl += context->vhost;  
216 - tcUrl += ":";  
217 - tcUrl += context->port;  
218 - tcUrl += "/";  
219 - tcUrl += context->app;  
220 -  
221 - if ((ret = context->rtmp->connect_app(context->app, tcUrl)) != ERROR_SUCCESS) {  
222 - return ret;  
223 - }  
224 -  
225 - return ret;  
226 -}  
227 -  
228 -int srs_play_stream(srs_rtmp_t rtmp)  
229 -{  
230 - int ret = ERROR_SUCCESS;  
231 -  
232 - srs_assert(rtmp != NULL);  
233 - Context* context = (Context*)rtmp;  
234 -  
235 - if ((ret = context->rtmp->create_stream(context->stream_id)) != ERROR_SUCCESS) {  
236 - return ret;  
237 - }  
238 - if ((ret = context->rtmp->play(context->stream, context->stream_id)) != ERROR_SUCCESS) {  
239 - return ret;  
240 - }  
241 -  
242 - return ERROR_SUCCESS;  
243 -}  
244 -  
245 -int srs_publish_stream(srs_rtmp_t rtmp)  
246 -{  
247 - return ERROR_SUCCESS;  
248 -}  
249 -  
250 -int srs_ssl_enabled()  
251 -{  
252 -#ifndef SRS_SSL  
253 - return false;  
254 -#endif  
255 - return true;  
256 -}  
257 -  
258 -int srs_version_major()  
259 -{  
260 - return ::atoi(VERSION_MAJOR);  
261 -}  
262 -  
263 -int srs_version_minor()  
264 -{  
265 - return ::atoi(VERSION_MINOR);  
266 -}  
267 -  
268 -int srs_version_revision()  
269 -{  
270 - return ::atoi(VERSION_REVISION);  
271 -}  
272 -  
273 -#ifdef __cplusplus  
274 -}  
275 -#endif 1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_librtmp.hpp>
  25 +
  26 +#include <stdlib.h>
  27 +
  28 +#include <string>
  29 +using namespace std;
  30 +
  31 +#include <srs_kernel_error.hpp>
  32 +#include <srs_protocol_rtmp.hpp>
  33 +#include <srs_lib_simple_socket.hpp>
  34 +#include <srs_kernel_log.hpp>
  35 +#include <srs_protocol_utility.hpp>
  36 +
  37 +// if user want to define log, define the folowing macro.
  38 +#ifndef SRS_RTMP_USER_DEFINED_LOG
  39 + // kernel module.
  40 + ISrsLog* _srs_log = new ISrsLog();
  41 + ISrsThreadContext* _srs_context = new ISrsThreadContext();
  42 +#endif
  43 +
  44 +/**
  45 +* export runtime context.
  46 +*/
  47 +struct Context
  48 +{
  49 + std::string url;
  50 + std::string tcUrl;
  51 + std::string host;
  52 + std::string port;
  53 + std::string vhost;
  54 + std::string app;
  55 + std::string stream;
  56 +
  57 + SrsRtmpClient* rtmp;
  58 + SimpleSocketStream* skt;
  59 + int stream_id;
  60 +
  61 + Context() {
  62 + rtmp = NULL;
  63 + skt = NULL;
  64 + stream_id = 0;
  65 + }
  66 + virtual ~Context() {
  67 + srs_freep(rtmp);
  68 + srs_freep(skt);
  69 + }
  70 +};
  71 +
  72 +int srs_librtmp_context_connect(Context* context)
  73 +{
  74 + int ret = ERROR_SUCCESS;
  75 +
  76 + // parse uri
  77 + size_t pos = string::npos;
  78 + string uri = context->url;
  79 + // tcUrl, stream
  80 + if ((pos = uri.rfind("/")) != string::npos) {
  81 + context->stream = uri.substr(pos + 1);
  82 + context->tcUrl = uri = uri.substr(0, pos);
  83 + }
  84 + // schema
  85 + if ((pos = uri.find("rtmp://")) != string::npos) {
  86 + uri = uri.substr(pos + 7);
  87 + }
  88 + // host/vhost/port
  89 + if ((pos = uri.find(":")) != string::npos) {
  90 + context->vhost = context->host = uri.substr(0, pos);
  91 + uri = uri.substr(pos + 1);
  92 +
  93 + if ((pos = uri.find("/")) != string::npos) {
  94 + context->port = uri.substr(0, pos);
  95 + uri = uri.substr(pos + 1);
  96 + }
  97 + } else {
  98 + if ((pos = uri.find("/")) != string::npos) {
  99 + context->vhost = context->host = uri.substr(0, pos);
  100 + uri = uri.substr(pos + 1);
  101 + }
  102 + context->port = RTMP_DEFAULT_PORT;
  103 + }
  104 + // app
  105 + context->app = uri;
  106 + // query of app
  107 + if ((pos = uri.find("?")) != string::npos) {
  108 + context->app = uri.substr(0, pos);
  109 + string query = uri.substr(pos + 1);
  110 + if ((pos = query.find("vhost=")) != string::npos) {
  111 + context->vhost = query.substr(pos + 6);
  112 + if ((pos = context->vhost.find("&")) != string::npos) {
  113 + context->vhost = context->vhost.substr(pos);
  114 + }
  115 + }
  116 + }
  117 +
  118 + // create socket
  119 + srs_freep(context->skt);
  120 + context->skt = new SimpleSocketStream();
  121 +
  122 + if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) {
  123 + return ret;
  124 + }
  125 +
  126 + // connect to server:port
  127 + string server = srs_dns_resolve(context->host);
  128 + if (server.empty()) {
  129 + return -1;
  130 + }
  131 + if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) {
  132 + return ret;
  133 + }
  134 +
  135 + return ret;
  136 +}
  137 +
  138 +#ifdef __cplusplus
  139 +extern "C"{
  140 +#endif
  141 +
  142 +srs_rtmp_t srs_rtmp_create(const char* url)
  143 +{
  144 + Context* context = new Context();
  145 + context->url = url;
  146 + return context;
  147 +}
  148 +
  149 +void srs_rtmp_destroy(srs_rtmp_t rtmp)
  150 +{
  151 + srs_assert(rtmp != NULL);
  152 + Context* context = (Context*)rtmp;
  153 +
  154 + srs_freep(context);
  155 +}
  156 +
  157 +int srs_simple_handshake(srs_rtmp_t rtmp)
  158 +{
  159 + int ret = ERROR_SUCCESS;
  160 +
  161 + srs_assert(rtmp != NULL);
  162 + Context* context = (Context*)rtmp;
  163 +
  164 + // parse uri, resolve host, connect to server:port
  165 + if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) {
  166 + return ret;
  167 + }
  168 +
  169 + // simple handshake
  170 + srs_freep(context->rtmp);
  171 + context->rtmp = new SrsRtmpClient(context->skt);
  172 +
  173 + if ((ret = context->rtmp->simple_handshake()) != ERROR_SUCCESS) {
  174 + return ret;
  175 + }
  176 +
  177 + return ret;
  178 +}
  179 +
  180 +int srs_complex_handshake(srs_rtmp_t rtmp)
  181 +{
  182 +#ifndef SRS_SSL
  183 + return ERROR_RTMP_HS_SSL_REQUIRE;
  184 +#endif
  185 +
  186 + int ret = ERROR_SUCCESS;
  187 +
  188 + srs_assert(rtmp != NULL);
  189 + Context* context = (Context*)rtmp;
  190 +
  191 + // parse uri, resolve host, connect to server:port
  192 + if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) {
  193 + return ret;
  194 + }
  195 +
  196 + // complex handshake
  197 + srs_freep(context->rtmp);
  198 + context->rtmp = new SrsRtmpClient(context->skt);
  199 +
  200 + if ((ret = context->rtmp->complex_handshake()) != ERROR_SUCCESS) {
  201 + return ret;
  202 + }
  203 +
  204 + return ret;
  205 +}
  206 +
  207 +int srs_connect_app(srs_rtmp_t rtmp)
  208 +{
  209 + int ret = ERROR_SUCCESS;
  210 +
  211 + srs_assert(rtmp != NULL);
  212 + Context* context = (Context*)rtmp;
  213 +
  214 + string tcUrl = "rtmp://";
  215 + tcUrl += context->vhost;
  216 + tcUrl += ":";
  217 + tcUrl += context->port;
  218 + tcUrl += "/";
  219 + tcUrl += context->app;
  220 +
  221 + if ((ret = context->rtmp->connect_app(context->app, tcUrl)) != ERROR_SUCCESS) {
  222 + return ret;
  223 + }
  224 +
  225 + return ret;
  226 +}
  227 +
  228 +int srs_play_stream(srs_rtmp_t rtmp)
  229 +{
  230 + int ret = ERROR_SUCCESS;
  231 +
  232 + srs_assert(rtmp != NULL);
  233 + Context* context = (Context*)rtmp;
  234 +
  235 + if ((ret = context->rtmp->create_stream(context->stream_id)) != ERROR_SUCCESS) {
  236 + return ret;
  237 + }
  238 + if ((ret = context->rtmp->play(context->stream, context->stream_id)) != ERROR_SUCCESS) {
  239 + return ret;
  240 + }
  241 +
  242 + return ret;
  243 +}
  244 +
  245 +int srs_publish_stream(srs_rtmp_t rtmp)
  246 +{
  247 + int ret = ERROR_SUCCESS;
  248 +
  249 + srs_assert(rtmp != NULL);
  250 + Context* context = (Context*)rtmp;
  251 +
  252 + return ret;
  253 +}
  254 +
  255 +int srs_ssl_enabled()
  256 +{
  257 +#ifndef SRS_SSL
  258 + return false;
  259 +#endif
  260 + return true;
  261 +}
  262 +
  263 +int srs_version_major()
  264 +{
  265 + return ::atoi(VERSION_MAJOR);
  266 +}
  267 +
  268 +int srs_version_minor()
  269 +{
  270 + return ::atoi(VERSION_MINOR);
  271 +}
  272 +
  273 +int srs_version_revision()
  274 +{
  275 + return ::atoi(VERSION_REVISION);
  276 +}
  277 +
  278 +#ifdef __cplusplus
  279 +}
  280 +#endif