正在显示
6 个修改的文件
包含
297 行增加
和
42 行删除
| @@ -26,34 +26,194 @@ gcc srs_rtmp_dump.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_rtmp_dum | @@ -26,34 +26,194 @@ gcc srs_rtmp_dump.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_rtmp_dum | ||
| 26 | 26 | ||
| 27 | #include <stdio.h> | 27 | #include <stdio.h> |
| 28 | #include <stdlib.h> | 28 | #include <stdlib.h> |
| 29 | +#include <unistd.h> | ||
| 30 | +#include <getopt.h> | ||
| 31 | +#include <assert.h> | ||
| 29 | 32 | ||
| 30 | #include "../../objs/include/srs_librtmp.h" | 33 | #include "../../objs/include/srs_librtmp.h" |
| 31 | 34 | ||
| 35 | +void parse_amf0_object(char* p, srs_amf0_t args) | ||
| 36 | +{ | ||
| 37 | + char opvt = 0; // object property value type. | ||
| 38 | + const char* opnp = NULL; // object property name ptr. | ||
| 39 | + const char* opvp = NULL; // object property value ptr. | ||
| 40 | + | ||
| 41 | + while (*p) { | ||
| 42 | + switch (*p++) { | ||
| 43 | + case 'O': | ||
| 44 | + while (*p && *p++ != ':') { | ||
| 45 | + } | ||
| 46 | + if (*p++ == '1') { | ||
| 47 | + printf("amf0 object start\n"); | ||
| 48 | + } else { | ||
| 49 | + printf("amf0 object end\n"); | ||
| 50 | + } | ||
| 51 | + break; | ||
| 52 | + case 'N': | ||
| 53 | + opvt = *p++; | ||
| 54 | + if (*p++ != ':') { | ||
| 55 | + printf("object property must split by :.\n"); | ||
| 56 | + exit(-1); | ||
| 57 | + } | ||
| 58 | + opnp = p++; | ||
| 59 | + while (*p && *p++ != ':') { | ||
| 60 | + } | ||
| 61 | + p[-1] = 0; | ||
| 62 | + opvp = p; | ||
| 63 | + printf("amf0 %c property[%s]=%s\n", opvt, opnp, opvp); | ||
| 64 | + switch(opvt) { | ||
| 65 | + case 'S': | ||
| 66 | + srs_amf0_object_property_set(args, opnp, srs_amf0_create_string(opvp)); | ||
| 67 | + break; | ||
| 68 | + default: | ||
| 69 | + printf("unsupported object property.\n"); | ||
| 70 | + exit(-1); | ||
| 71 | + } | ||
| 72 | + *p=0; | ||
| 73 | + break; | ||
| 74 | + default: | ||
| 75 | + printf("only supports an object arg.\n"); | ||
| 76 | + exit(-1); | ||
| 77 | + } | ||
| 78 | + } | ||
| 79 | +} | ||
| 80 | + | ||
| 32 | int main(int argc, char** argv) | 81 | int main(int argc, char** argv) |
| 33 | { | 82 | { |
| 34 | printf("dump rtmp stream to flv file\n"); | 83 | printf("dump rtmp stream to flv file\n"); |
| 35 | printf("srs(simple-rtmp-server) client librtmp library.\n"); | 84 | printf("srs(simple-rtmp-server) client librtmp library.\n"); |
| 36 | printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | 85 | printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); |
| 86 | + printf("@refer to http://rtmpdump.mplayerhq.hu/rtmpdump.1.html\n"); | ||
| 87 | + | ||
| 88 | + struct option long_options[] = { | ||
| 89 | + {"rtmp", required_argument, 0, 'r'}, | ||
| 90 | + {"flv", required_argument, 0, 'o'}, | ||
| 91 | + {"swfUrl", required_argument, 0, 's'}, | ||
| 92 | + {"tcUrl", required_argument, 0, 't'}, | ||
| 93 | + {"pageUrl", required_argument, 0, 'p'}, | ||
| 94 | + {"conn", required_argument, 0, 'C'}, | ||
| 95 | + {"complex", no_argument, 0, 'x'}, | ||
| 96 | + {"help", no_argument, 0, 'h'}, | ||
| 97 | + {0, 0, 0, 0} | ||
| 98 | + }; | ||
| 99 | + | ||
| 100 | + int show_help = 0; | ||
| 101 | + int complex_handshake = 0; | ||
| 102 | + const char* rtmp_url = NULL; | ||
| 103 | + const char* output_flv = NULL; | ||
| 104 | + const char* swfUrl = NULL; | ||
| 105 | + const char* tcUrl = NULL; | ||
| 106 | + const char* pageUrl = NULL; | ||
| 107 | + srs_amf0_t args = NULL; | ||
| 37 | 108 | ||
| 38 | - if (argc <= 2) { | ||
| 39 | - printf("Usage: %s <rtmp_url> <flv_path>\n" | ||
| 40 | - " rtmp_url RTMP stream url to play\n" | ||
| 41 | - " flv_path The flv file path to save\n" | 109 | + int opt = 0; |
| 110 | + int option_index = 0; | ||
| 111 | + while((opt = getopt_long(argc, argv, "hxr:o:s:t:p:C:", long_options, &option_index)) != -1){ | ||
| 112 | + switch(opt){ | ||
| 113 | + case 'r': | ||
| 114 | + rtmp_url = optarg; | ||
| 115 | + break; | ||
| 116 | + case 'o': | ||
| 117 | + output_flv = optarg; | ||
| 118 | + break; | ||
| 119 | + case 's': | ||
| 120 | + swfUrl = optarg; | ||
| 121 | + break; | ||
| 122 | + case 't': | ||
| 123 | + tcUrl = optarg; | ||
| 124 | + break; | ||
| 125 | + case 'p': | ||
| 126 | + pageUrl = optarg; | ||
| 127 | + break; | ||
| 128 | + case 'C': | ||
| 129 | + if (!args) { | ||
| 130 | + args = srs_amf0_create_object(); | ||
| 131 | + } | ||
| 132 | + char* p = (char*)optarg; | ||
| 133 | + parse_amf0_object(p, args); | ||
| 134 | + break; | ||
| 135 | + case 'x': | ||
| 136 | + complex_handshake = 1; | ||
| 137 | + break; | ||
| 138 | + case 'h': | ||
| 139 | + show_help = 1; | ||
| 140 | + break; | ||
| 141 | + default: | ||
| 142 | + printf("unsupported opt.\n"); | ||
| 143 | + exit(-1); | ||
| 144 | + } | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + if (!rtmp_url || show_help) { | ||
| 148 | + printf("Usage: %s -r url [-o output] [-s swfUrl] [-t tcUrl] [-p pageUrl] [-C conndata] [--complex] [-h]\n" | ||
| 149 | + "Options:\n" | ||
| 150 | + " --rtmp -r url\n" | ||
| 151 | + " URL of the server and media content.\n" | ||
| 152 | + " --flv -o output\n" | ||
| 153 | + " Specify the output file name. If the name is − or is omitted, the stream is written to stdout.\n" | ||
| 154 | + " --complex\n" | ||
| 155 | + " Whether use complex handshake(srs-librtmp with ssl required).\n" | ||
| 156 | + " --swfUrl -s url\n" | ||
| 157 | + " URL of the SWF player for the media. By default no value will be sent.\n" | ||
| 158 | + " --tcUrl -t url\n" | ||
| 159 | + " URL of the target stream. Defaults to rtmp[e]://host[:port]/app/playpath.\n" | ||
| 160 | + " --pageUrl -p url\n" | ||
| 161 | + " URL of the web page in which the media was embedded. By default no value will be sent.\n" | ||
| 162 | + " −−conn −C type:data\n" | ||
| 163 | + " Append arbitrary AMF data to the Connect message. The type must be B for Boolean, N for number, S for string, O for object, or Z for null. For Booleans the data must be either 0 or 1 for FALSE or TRUE, respectively. Likewise for Objects the data must be 0 or 1 to end or begin an object, respectively. Data items in subobjects may be named, by prefixing the type with 'N' and specifying the name before the value, e.g. NB:myFlag:1. This option may be used multiple times to construct arbitrary AMF sequences. E.g.\n" | ||
| 164 | + " −C B:1 −C S:authMe −C O:1 −C NN:code:1.23 −C NS:flag:ok −C O:0\n" | ||
| 165 | + " -C O:1 -C NS:CONN:\" -C B:4Rg9vr0\" -C O:0\n" | ||
| 166 | + " @remark, support a object args only.\n" | ||
| 167 | + " --help -h\n" | ||
| 168 | + " Print a summary of command options.\n" | ||
| 42 | "For example:\n" | 169 | "For example:\n" |
| 43 | - " %s rtmp://127.0.0.1:1935/live/livestream output.flv\n", | ||
| 44 | - argv[0], argv[0]); | 170 | + " %s -r rtmp://127.0.0.1:1935/live/livestream -o output.flv\n" |
| 171 | + " %s -h\n", | ||
| 172 | + argv[0], argv[0], argv[0]); | ||
| 45 | exit(-1); | 173 | exit(-1); |
| 46 | } | 174 | } |
| 47 | 175 | ||
| 48 | - srs_human_trace("rtmp url: %s", argv[1]); | ||
| 49 | - srs_human_trace("flv path: %s", argv[2]); | ||
| 50 | - srs_rtmp_t rtmp = srs_rtmp_create(argv[1]); | 176 | + srs_human_trace("rtmp url: %s", rtmp_url); |
| 177 | + srs_human_trace("handshake: %s", (complex_handshake? "complex" : "simple")); | ||
| 178 | + srs_human_trace("swfUrl: %s", swfUrl); | ||
| 179 | + srs_human_trace("pageUrl: %s", pageUrl); | ||
| 180 | + srs_human_trace("tcUrl: %s", tcUrl); | ||
| 181 | + if (output_flv) { | ||
| 182 | + srs_human_trace("flv output path: %s", output_flv); | ||
| 183 | + } else { | ||
| 184 | + srs_human_trace("output to console"); | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url); | ||
| 188 | + | ||
| 189 | + if (__srs_rtmp_dns_resolve(rtmp) != 0) { | ||
| 190 | + srs_human_trace("dns resolve failed."); | ||
| 191 | + goto rtmp_destroy; | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + if (__srs_rtmp_connect_server(rtmp) != 0) { | ||
| 195 | + srs_human_trace("connect to server failed."); | ||
| 196 | + goto rtmp_destroy; | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + if (complex_handshake) { | ||
| 200 | + if (__srs_rtmp_do_complex_handshake(rtmp) != 0) { | ||
| 201 | + srs_human_trace("complex handshake failed."); | ||
| 202 | + goto rtmp_destroy; | ||
| 203 | + } | ||
| 204 | + srs_human_trace("do complex handshake success"); | ||
| 205 | + } else { | ||
| 206 | + if (__srs_rtmp_do_simple_handshake(rtmp) != 0) { | ||
| 207 | + srs_human_trace("simple handshake failed."); | ||
| 208 | + goto rtmp_destroy; | ||
| 209 | + } | ||
| 210 | + srs_human_trace("do simple handshake success"); | ||
| 211 | + } | ||
| 51 | 212 | ||
| 52 | - if (srs_rtmp_handshake(rtmp) != 0) { | ||
| 53 | - srs_human_trace("simple handshake failed."); | 213 | + if (srs_rtmp_set_connect_args(rtmp, tcUrl, swfUrl, pageUrl, args) != 0) { |
| 214 | + srs_human_trace("set connect args failed."); | ||
| 54 | goto rtmp_destroy; | 215 | goto rtmp_destroy; |
| 55 | } | 216 | } |
| 56 | - srs_human_trace("simple handshake success"); | ||
| 57 | 217 | ||
| 58 | if (srs_rtmp_connect_app(rtmp) != 0) { | 218 | if (srs_rtmp_connect_app(rtmp) != 0) { |
| 59 | srs_human_trace("connect vhost/app failed."); | 219 | srs_human_trace("connect vhost/app failed."); |
| @@ -67,26 +227,31 @@ int main(int argc, char** argv) | @@ -67,26 +227,31 @@ int main(int argc, char** argv) | ||
| 67 | } | 227 | } |
| 68 | srs_human_trace("play stream success"); | 228 | srs_human_trace("play stream success"); |
| 69 | 229 | ||
| 70 | - srs_flv_t flv = srs_flv_open_write(argv[2]); | ||
| 71 | - | ||
| 72 | - // flv header | ||
| 73 | - char header[9]; | ||
| 74 | - // 3bytes, signature, "FLV", | ||
| 75 | - header[0] = 'F'; | ||
| 76 | - header[1] = 'L'; | ||
| 77 | - header[2] = 'V'; | ||
| 78 | - // 1bytes, version, 0x01, | ||
| 79 | - header[3] = 0x01; | ||
| 80 | - // 1bytes, flags, UB[5] 0, UB[1] audio present, UB[1] 0, UB[1] video present. | ||
| 81 | - header[4] = 0x03; // audio + video. | ||
| 82 | - // 4bytes, dataoffset | ||
| 83 | - header[5] = 0x00; | ||
| 84 | - header[6] = 0x00; | ||
| 85 | - header[7] = 0x00; | ||
| 86 | - header[8] = 0x09; | ||
| 87 | - if (srs_flv_write_header(flv, header) != 0) { | ||
| 88 | - srs_human_trace("write flv header failed."); | ||
| 89 | - goto rtmp_destroy; | 230 | + srs_flv_t flv = NULL; |
| 231 | + if (output_flv) { | ||
| 232 | + flv = srs_flv_open_write(output_flv); | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + if (flv) { | ||
| 236 | + // flv header | ||
| 237 | + char header[9]; | ||
| 238 | + // 3bytes, signature, "FLV", | ||
| 239 | + header[0] = 'F'; | ||
| 240 | + header[1] = 'L'; | ||
| 241 | + header[2] = 'V'; | ||
| 242 | + // 1bytes, version, 0x01, | ||
| 243 | + header[3] = 0x01; | ||
| 244 | + // 1bytes, flags, UB[5] 0, UB[1] audio present, UB[1] 0, UB[1] video present. | ||
| 245 | + header[4] = 0x03; // audio + video. | ||
| 246 | + // 4bytes, dataoffset | ||
| 247 | + header[5] = 0x00; | ||
| 248 | + header[6] = 0x00; | ||
| 249 | + header[7] = 0x00; | ||
| 250 | + header[8] = 0x09; | ||
| 251 | + if (srs_flv_write_header(flv, header) != 0) { | ||
| 252 | + srs_human_trace("write flv header failed."); | ||
| 253 | + goto rtmp_destroy; | ||
| 254 | + } | ||
| 90 | } | 255 | } |
| 91 | 256 | ||
| 92 | for (;;) { | 257 | for (;;) { |
| @@ -105,9 +270,11 @@ int main(int argc, char** argv) | @@ -105,9 +270,11 @@ int main(int argc, char** argv) | ||
| 105 | goto rtmp_destroy; | 270 | goto rtmp_destroy; |
| 106 | } | 271 | } |
| 107 | 272 | ||
| 108 | - if (srs_flv_write_tag(flv, type, timestamp, data, size) != 0) { | ||
| 109 | - srs_human_trace("dump rtmp packet failed."); | ||
| 110 | - goto rtmp_destroy; | 273 | + if (flv) { |
| 274 | + if (srs_flv_write_tag(flv, type, timestamp, data, size) != 0) { | ||
| 275 | + srs_human_trace("dump rtmp packet failed."); | ||
| 276 | + goto rtmp_destroy; | ||
| 277 | + } | ||
| 111 | } | 278 | } |
| 112 | 279 | ||
| 113 | free(data); | 280 | free(data); |
| @@ -115,7 +282,9 @@ int main(int argc, char** argv) | @@ -115,7 +282,9 @@ int main(int argc, char** argv) | ||
| 115 | 282 | ||
| 116 | rtmp_destroy: | 283 | rtmp_destroy: |
| 117 | srs_rtmp_destroy(rtmp); | 284 | srs_rtmp_destroy(rtmp); |
| 118 | - srs_flv_close(flv); | 285 | + if (flv) { |
| 286 | + srs_flv_close(flv); | ||
| 287 | + } | ||
| 119 | srs_human_trace("completed"); | 288 | srs_human_trace("completed"); |
| 120 | 289 | ||
| 121 | return 0; | 290 | return 0; |
| @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | // current release version | 31 | // current release version |
| 32 | #define VERSION_MAJOR 2 | 32 | #define VERSION_MAJOR 2 |
| 33 | #define VERSION_MINOR 0 | 33 | #define VERSION_MINOR 0 |
| 34 | -#define VERSION_REVISION 89 | 34 | +#define VERSION_REVISION 90 |
| 35 | // server info. | 35 | // server info. |
| 36 | #define RTMP_SIG_SRS_KEY "SRS" | 36 | #define RTMP_SIG_SRS_KEY "SRS" |
| 37 | #define RTMP_SIG_SRS_ROLE "origin/edge server" | 37 | #define RTMP_SIG_SRS_ROLE "origin/edge server" |
| @@ -66,6 +66,9 @@ struct Context | @@ -66,6 +66,9 @@ struct Context | ||
| 66 | std::string app; | 66 | std::string app; |
| 67 | std::string stream; | 67 | std::string stream; |
| 68 | std::string param; | 68 | std::string param; |
| 69 | + | ||
| 70 | + // extra request object for connect to server, NULL to ignore. | ||
| 71 | + SrsRequest* req; | ||
| 69 | 72 | ||
| 70 | SrsRtmpClient* rtmp; | 73 | SrsRtmpClient* rtmp; |
| 71 | SimpleSocketStream* skt; | 74 | SimpleSocketStream* skt; |
| @@ -93,12 +96,14 @@ struct Context | @@ -93,12 +96,14 @@ struct Context | ||
| 93 | Context() { | 96 | Context() { |
| 94 | rtmp = NULL; | 97 | rtmp = NULL; |
| 95 | skt = NULL; | 98 | skt = NULL; |
| 99 | + req = NULL; | ||
| 96 | stream_id = 0; | 100 | stream_id = 0; |
| 97 | h264_sps_pps_sent = false; | 101 | h264_sps_pps_sent = false; |
| 98 | h264_sps_changed = false; | 102 | h264_sps_changed = false; |
| 99 | h264_pps_changed = false; | 103 | h264_pps_changed = false; |
| 100 | } | 104 | } |
| 101 | virtual ~Context() { | 105 | virtual ~Context() { |
| 106 | + srs_freep(req); | ||
| 102 | srs_freep(rtmp); | 107 | srs_freep(rtmp); |
| 103 | srs_freep(skt); | 108 | srs_freep(skt); |
| 104 | } | 109 | } |
| @@ -595,6 +600,53 @@ int __srs_rtmp_connect_server(srs_rtmp_t rtmp) | @@ -595,6 +600,53 @@ int __srs_rtmp_connect_server(srs_rtmp_t rtmp) | ||
| 595 | return ret; | 600 | return ret; |
| 596 | } | 601 | } |
| 597 | 602 | ||
| 603 | +int __srs_rtmp_do_complex_handshake(srs_rtmp_t rtmp) | ||
| 604 | +{ | ||
| 605 | + int ret = ERROR_SUCCESS; | ||
| 606 | + | ||
| 607 | + srs_assert(rtmp != NULL); | ||
| 608 | + Context* context = (Context*)rtmp; | ||
| 609 | + | ||
| 610 | + srs_assert(context->skt != NULL); | ||
| 611 | + | ||
| 612 | + // simple handshake | ||
| 613 | + srs_freep(context->rtmp); | ||
| 614 | + context->rtmp = new SrsRtmpClient(context->skt); | ||
| 615 | + | ||
| 616 | + if ((ret = context->rtmp->complex_handshake()) != ERROR_SUCCESS) { | ||
| 617 | + return ret; | ||
| 618 | + } | ||
| 619 | + | ||
| 620 | + return ret; | ||
| 621 | +} | ||
| 622 | + | ||
| 623 | +int srs_rtmp_set_connect_args(srs_rtmp_t rtmp, | ||
| 624 | + const char* tcUrl, const char* swfUrl, const char* pageUrl, srs_amf0_t args | ||
| 625 | +) { | ||
| 626 | + int ret = ERROR_SUCCESS; | ||
| 627 | + | ||
| 628 | + srs_assert(rtmp != NULL); | ||
| 629 | + Context* context = (Context*)rtmp; | ||
| 630 | + | ||
| 631 | + srs_freep(context->req); | ||
| 632 | + context->req = new SrsRequest(); | ||
| 633 | + | ||
| 634 | + if (args) { | ||
| 635 | + context->req->args = (SrsAmf0Object*)args; | ||
| 636 | + } | ||
| 637 | + if (tcUrl) { | ||
| 638 | + context->req->tcUrl = tcUrl; | ||
| 639 | + } | ||
| 640 | + if (swfUrl) { | ||
| 641 | + context->req->swfUrl = swfUrl; | ||
| 642 | + } | ||
| 643 | + if (pageUrl) { | ||
| 644 | + context->req->pageUrl = pageUrl; | ||
| 645 | + } | ||
| 646 | + | ||
| 647 | + return ret; | ||
| 648 | +} | ||
| 649 | + | ||
| 598 | int __srs_rtmp_do_simple_handshake(srs_rtmp_t rtmp) | 650 | int __srs_rtmp_do_simple_handshake(srs_rtmp_t rtmp) |
| 599 | { | 651 | { |
| 600 | int ret = ERROR_SUCCESS; | 652 | int ret = ERROR_SUCCESS; |
| @@ -628,7 +680,7 @@ int srs_rtmp_connect_app(srs_rtmp_t rtmp) | @@ -628,7 +680,7 @@ int srs_rtmp_connect_app(srs_rtmp_t rtmp) | ||
| 628 | ); | 680 | ); |
| 629 | 681 | ||
| 630 | if ((ret = context->rtmp->connect_app( | 682 | if ((ret = context->rtmp->connect_app( |
| 631 | - context->app, tcUrl, NULL, true)) != ERROR_SUCCESS) | 683 | + context->app, tcUrl, context->req, true)) != ERROR_SUCCESS) |
| 632 | { | 684 | { |
| 633 | return ret; | 685 | return ret; |
| 634 | } | 686 | } |
| @@ -1725,6 +1777,11 @@ srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed) | @@ -1725,6 +1777,11 @@ srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed) | ||
| 1725 | return amf0; | 1777 | return amf0; |
| 1726 | } | 1778 | } |
| 1727 | 1779 | ||
| 1780 | +srs_amf0_t srs_amf0_create_string(const char* value) | ||
| 1781 | +{ | ||
| 1782 | + return SrsAmf0Any::str(value); | ||
| 1783 | +} | ||
| 1784 | + | ||
| 1728 | srs_amf0_t srs_amf0_create_number(srs_amf0_number value) | 1785 | srs_amf0_t srs_amf0_create_number(srs_amf0_number value) |
| 1729 | { | 1786 | { |
| 1730 | return SrsAmf0Any::number(value); | 1787 | return SrsAmf0Any::number(value); |
| @@ -2374,6 +2431,9 @@ int srs_human_print_rtmp_packet(char type, u_int32_t timestamp, char* data, int | @@ -2374,6 +2431,9 @@ int srs_human_print_rtmp_packet(char type, u_int32_t timestamp, char* data, int | ||
| 2374 | 2431 | ||
| 2375 | u_int32_t pts; | 2432 | u_int32_t pts; |
| 2376 | if (srs_utils_parse_timestamp(timestamp, type, data, size, &pts) != 0) { | 2433 | if (srs_utils_parse_timestamp(timestamp, type, data, size, &pts) != 0) { |
| 2434 | + srs_human_trace("Video packet type=%s, dts=%d, pts=%d, size=%d, DecodeError", | ||
| 2435 | + srs_human_flv_tag_type2string(type), timestamp, pts, size | ||
| 2436 | + ); | ||
| 2377 | return ret; | 2437 | return ret; |
| 2378 | } | 2438 | } |
| 2379 | 2439 |
| @@ -86,6 +86,7 @@ extern int srs_version_revision(); | @@ -86,6 +86,7 @@ extern int srs_version_revision(); | ||
| 86 | *************************************************************/ | 86 | *************************************************************/ |
| 87 | // the RTMP handler. | 87 | // the RTMP handler. |
| 88 | typedef void* srs_rtmp_t; | 88 | typedef void* srs_rtmp_t; |
| 89 | +typedef void* srs_amf0_t; | ||
| 89 | 90 | ||
| 90 | /** | 91 | /** |
| 91 | * create/destroy a rtmp protocol stack. | 92 | * create/destroy a rtmp protocol stack. |
| @@ -142,6 +143,18 @@ extern int __srs_rtmp_dns_resolve(srs_rtmp_t rtmp); | @@ -142,6 +143,18 @@ extern int __srs_rtmp_dns_resolve(srs_rtmp_t rtmp); | ||
| 142 | extern int __srs_rtmp_connect_server(srs_rtmp_t rtmp); | 143 | extern int __srs_rtmp_connect_server(srs_rtmp_t rtmp); |
| 143 | // do simple handshake over socket. | 144 | // do simple handshake over socket. |
| 144 | extern int __srs_rtmp_do_simple_handshake(srs_rtmp_t rtmp); | 145 | extern int __srs_rtmp_do_simple_handshake(srs_rtmp_t rtmp); |
| 146 | +// do complex handshake over socket. | ||
| 147 | +extern int __srs_rtmp_do_complex_handshake(srs_rtmp_t rtmp); | ||
| 148 | + | ||
| 149 | +/** | ||
| 150 | +* set the args of connect packet for rtmp. | ||
| 151 | +* @param args, the extra amf0 object args. | ||
| 152 | +* @remark, all params can be NULL to ignore. | ||
| 153 | +* @remark, user should never free the args for we directly use it. | ||
| 154 | +*/ | ||
| 155 | +extern int srs_rtmp_set_connect_args(srs_rtmp_t rtmp, | ||
| 156 | + const char* tcUrl, const char* swfUrl, const char* pageUrl, srs_amf0_t args | ||
| 157 | +); | ||
| 145 | 158 | ||
| 146 | /** | 159 | /** |
| 147 | * connect to rtmp vhost/app | 160 | * connect to rtmp vhost/app |
| @@ -546,7 +559,6 @@ extern srs_bool srs_flv_is_keyframe(char* data, int32_t size); | @@ -546,7 +559,6 @@ extern srs_bool srs_flv_is_keyframe(char* data, int32_t size); | ||
| 546 | ************************************************************** | 559 | ************************************************************** |
| 547 | *************************************************************/ | 560 | *************************************************************/ |
| 548 | /* the output handler. */ | 561 | /* the output handler. */ |
| 549 | -typedef void* srs_amf0_t; | ||
| 550 | typedef double srs_amf0_number; | 562 | typedef double srs_amf0_number; |
| 551 | /** | 563 | /** |
| 552 | * parse amf0 from data. | 564 | * parse amf0 from data. |
| @@ -555,6 +567,7 @@ typedef double srs_amf0_number; | @@ -555,6 +567,7 @@ typedef double srs_amf0_number; | ||
| 555 | * @remark user must free the parsed or created object by srs_amf0_free. | 567 | * @remark user must free the parsed or created object by srs_amf0_free. |
| 556 | */ | 568 | */ |
| 557 | extern srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed); | 569 | extern srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed); |
| 570 | +extern srs_amf0_t srs_amf0_create_string(const char* value); | ||
| 558 | extern srs_amf0_t srs_amf0_create_number(srs_amf0_number value); | 571 | extern srs_amf0_t srs_amf0_create_number(srs_amf0_number value); |
| 559 | extern srs_amf0_t srs_amf0_create_ecma_array(); | 572 | extern srs_amf0_t srs_amf0_create_ecma_array(); |
| 560 | extern srs_amf0_t srs_amf0_create_strict_array(); | 573 | extern srs_amf0_t srs_amf0_create_strict_array(); |
| @@ -469,13 +469,17 @@ int SrsRtmpClient::connect_app2( | @@ -469,13 +469,17 @@ int SrsRtmpClient::connect_app2( | ||
| 469 | SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); | 469 | SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); |
| 470 | 470 | ||
| 471 | pkt->command_object->set("app", SrsAmf0Any::str(app.c_str())); | 471 | pkt->command_object->set("app", SrsAmf0Any::str(app.c_str())); |
| 472 | - pkt->command_object->set("flashVer", SrsAmf0Any::str("WIN 12,0,0,41")); | 472 | + pkt->command_object->set("flashVer", SrsAmf0Any::str("WIN 15,0,0,239")); |
| 473 | if (req) { | 473 | if (req) { |
| 474 | pkt->command_object->set("swfUrl", SrsAmf0Any::str(req->swfUrl.c_str())); | 474 | pkt->command_object->set("swfUrl", SrsAmf0Any::str(req->swfUrl.c_str())); |
| 475 | } else { | 475 | } else { |
| 476 | pkt->command_object->set("swfUrl", SrsAmf0Any::str()); | 476 | pkt->command_object->set("swfUrl", SrsAmf0Any::str()); |
| 477 | } | 477 | } |
| 478 | - pkt->command_object->set("tcUrl", SrsAmf0Any::str(tc_url.c_str())); | 478 | + if (req && req->tcUrl != "") { |
| 479 | + pkt->command_object->set("tcUrl", SrsAmf0Any::str(req->tcUrl.c_str())); | ||
| 480 | + } else { | ||
| 481 | + pkt->command_object->set("tcUrl", SrsAmf0Any::str(tc_url.c_str())); | ||
| 482 | + } | ||
| 479 | pkt->command_object->set("fpad", SrsAmf0Any::boolean(false)); | 483 | pkt->command_object->set("fpad", SrsAmf0Any::boolean(false)); |
| 480 | pkt->command_object->set("capabilities", SrsAmf0Any::number(239)); | 484 | pkt->command_object->set("capabilities", SrsAmf0Any::number(239)); |
| 481 | pkt->command_object->set("audioCodecs", SrsAmf0Any::number(3575)); | 485 | pkt->command_object->set("audioCodecs", SrsAmf0Any::number(3575)); |
| @@ -31,7 +31,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | #include <srs_protocol_buffer.hpp> | 31 | #include <srs_protocol_buffer.hpp> |
| 32 | #include <srs_protocol_utility.hpp> | 32 | #include <srs_protocol_utility.hpp> |
| 33 | 33 | ||
| 34 | +// for srs-librtmp, @see https://github.com/winlinvip/simple-rtmp-server/issues/213 | ||
| 35 | +#ifndef _WIN32 | ||
| 34 | #include <unistd.h> | 36 | #include <unistd.h> |
| 37 | +#endif | ||
| 38 | + | ||
| 35 | #include <stdlib.h> | 39 | #include <stdlib.h> |
| 36 | using namespace std; | 40 | using namespace std; |
| 37 | 41 | ||
| @@ -868,9 +872,14 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | @@ -868,9 +872,14 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | ||
| 868 | int SrsProtocol::do_iovs_send(iovec* iovs, int size) | 872 | int SrsProtocol::do_iovs_send(iovec* iovs, int size) |
| 869 | { | 873 | { |
| 870 | int ret = ERROR_SUCCESS; | 874 | int ret = ERROR_SUCCESS; |
| 871 | - | 875 | + |
| 872 | // the limits of writev iovs. | 876 | // the limits of writev iovs. |
| 877 | + // for srs-librtmp, @see https://github.com/winlinvip/simple-rtmp-server/issues/213 | ||
| 878 | +#ifndef _WIN32 | ||
| 873 | static int limits = sysconf(_SC_IOV_MAX); | 879 | static int limits = sysconf(_SC_IOV_MAX); |
| 880 | +#else | ||
| 881 | + static int limits = 1024; | ||
| 882 | +#endif | ||
| 874 | 883 | ||
| 875 | // send in a time. | 884 | // send in a time. |
| 876 | if (size < limits) { | 885 | if (size < limits) { |
-
请 注册 或 登录 后发表评论