1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

for bug #215, srs rtmp dump support conn args. 2.0.90

This commit is contained in:
winlin 2015-01-07 13:29:30 +08:00
parent 4c18234678
commit 0e03d019a8
6 changed files with 296 additions and 41 deletions

View file

@ -26,34 +26,194 @@ gcc srs_rtmp_dump.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_rtmp_dum
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <assert.h>
#include "../../objs/include/srs_librtmp.h"
void parse_amf0_object(char* p, srs_amf0_t args)
{
char opvt = 0; // object property value type.
const char* opnp = NULL; // object property name ptr.
const char* opvp = NULL; // object property value ptr.
while (*p) {
switch (*p++) {
case 'O':
while (*p && *p++ != ':') {
}
if (*p++ == '1') {
printf("amf0 object start\n");
} else {
printf("amf0 object end\n");
}
break;
case 'N':
opvt = *p++;
if (*p++ != ':') {
printf("object property must split by :.\n");
exit(-1);
}
opnp = p++;
while (*p && *p++ != ':') {
}
p[-1] = 0;
opvp = p;
printf("amf0 %c property[%s]=%s\n", opvt, opnp, opvp);
switch(opvt) {
case 'S':
srs_amf0_object_property_set(args, opnp, srs_amf0_create_string(opvp));
break;
default:
printf("unsupported object property.\n");
exit(-1);
}
*p=0;
break;
default:
printf("only supports an object arg.\n");
exit(-1);
}
}
}
int main(int argc, char** argv)
{
printf("dump rtmp stream to flv file\n");
printf("srs(simple-rtmp-server) client librtmp library.\n");
printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());
printf("@refer to http://rtmpdump.mplayerhq.hu/rtmpdump.1.html\n");
if (argc <= 2) {
printf("Usage: %s <rtmp_url> <flv_path>\n"
" rtmp_url RTMP stream url to play\n"
" flv_path The flv file path to save\n"
struct option long_options[] = {
{"rtmp", required_argument, 0, 'r'},
{"flv", required_argument, 0, 'o'},
{"swfUrl", required_argument, 0, 's'},
{"tcUrl", required_argument, 0, 't'},
{"pageUrl", required_argument, 0, 'p'},
{"conn", required_argument, 0, 'C'},
{"complex", no_argument, 0, 'x'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
int show_help = 0;
int complex_handshake = 0;
const char* rtmp_url = NULL;
const char* output_flv = NULL;
const char* swfUrl = NULL;
const char* tcUrl = NULL;
const char* pageUrl = NULL;
srs_amf0_t args = NULL;
int opt = 0;
int option_index = 0;
while((opt = getopt_long(argc, argv, "hxr:o:s:t:p:C:", long_options, &option_index)) != -1){
switch(opt){
case 'r':
rtmp_url = optarg;
break;
case 'o':
output_flv = optarg;
break;
case 's':
swfUrl = optarg;
break;
case 't':
tcUrl = optarg;
break;
case 'p':
pageUrl = optarg;
break;
case 'C':
if (!args) {
args = srs_amf0_create_object();
}
char* p = (char*)optarg;
parse_amf0_object(p, args);
break;
case 'x':
complex_handshake = 1;
break;
case 'h':
show_help = 1;
break;
default:
printf("unsupported opt.\n");
exit(-1);
}
}
if (!rtmp_url || show_help) {
printf("Usage: %s -r url [-o output] [-s swfUrl] [-t tcUrl] [-p pageUrl] [-C conndata] [--complex] [-h]\n"
"Options:\n"
" --rtmp -r url\n"
" URL of the server and media content.\n"
" --flv -o output\n"
" Specify the output file name. If the name is or is omitted, the stream is written to stdout.\n"
" --complex\n"
" Whether use complex handshake(srs-librtmp with ssl required).\n"
" --swfUrl -s url\n"
" URL of the SWF player for the media. By default no value will be sent.\n"
" --tcUrl -t url\n"
" URL of the target stream. Defaults to rtmp[e]://host[:port]/app/playpath.\n"
" --pageUrl -p url\n"
" URL of the web page in which the media was embedded. By default no value will be sent.\n"
" conn C type:data\n"
" 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"
" C B:1 C S:authMe C O:1 C NN:code:1.23 C NS:flag:ok C O:0\n"
" -C O:1 -C NS:CONN:\" -C B:4Rg9vr0\" -C O:0\n"
" @remark, support a object args only.\n"
" --help -h\n"
" Print a summary of command options.\n"
"For example:\n"
" %s rtmp://127.0.0.1:1935/live/livestream output.flv\n",
argv[0], argv[0]);
" %s -r rtmp://127.0.0.1:1935/live/livestream -o output.flv\n"
" %s -h\n",
argv[0], argv[0], argv[0]);
exit(-1);
}
srs_human_trace("rtmp url: %s", argv[1]);
srs_human_trace("flv path: %s", argv[2]);
srs_rtmp_t rtmp = srs_rtmp_create(argv[1]);
srs_human_trace("rtmp url: %s", rtmp_url);
srs_human_trace("handshake: %s", (complex_handshake? "complex" : "simple"));
srs_human_trace("swfUrl: %s", swfUrl);
srs_human_trace("pageUrl: %s", pageUrl);
srs_human_trace("tcUrl: %s", tcUrl);
if (output_flv) {
srs_human_trace("flv output path: %s", output_flv);
} else {
srs_human_trace("output to console");
}
if (srs_rtmp_handshake(rtmp) != 0) {
srs_human_trace("simple handshake failed.");
srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url);
if (__srs_rtmp_dns_resolve(rtmp) != 0) {
srs_human_trace("dns resolve failed.");
goto rtmp_destroy;
}
if (__srs_rtmp_connect_server(rtmp) != 0) {
srs_human_trace("connect to server failed.");
goto rtmp_destroy;
}
if (complex_handshake) {
if (__srs_rtmp_do_complex_handshake(rtmp) != 0) {
srs_human_trace("complex handshake failed.");
goto rtmp_destroy;
}
srs_human_trace("do complex handshake success");
} else {
if (__srs_rtmp_do_simple_handshake(rtmp) != 0) {
srs_human_trace("simple handshake failed.");
goto rtmp_destroy;
}
srs_human_trace("do simple handshake success");
}
if (srs_rtmp_set_connect_args(rtmp, tcUrl, swfUrl, pageUrl, args) != 0) {
srs_human_trace("set connect args failed.");
goto rtmp_destroy;
}
srs_human_trace("simple handshake success");
if (srs_rtmp_connect_app(rtmp) != 0) {
srs_human_trace("connect vhost/app failed.");
@ -67,26 +227,31 @@ int main(int argc, char** argv)
}
srs_human_trace("play stream success");
srs_flv_t flv = srs_flv_open_write(argv[2]);
srs_flv_t flv = NULL;
if (output_flv) {
flv = srs_flv_open_write(output_flv);
}
// flv header
char header[9];
// 3bytes, signature, "FLV",
header[0] = 'F';
header[1] = 'L';
header[2] = 'V';
// 1bytes, version, 0x01,
header[3] = 0x01;
// 1bytes, flags, UB[5] 0, UB[1] audio present, UB[1] 0, UB[1] video present.
header[4] = 0x03; // audio + video.
// 4bytes, dataoffset
header[5] = 0x00;
header[6] = 0x00;
header[7] = 0x00;
header[8] = 0x09;
if (srs_flv_write_header(flv, header) != 0) {
srs_human_trace("write flv header failed.");
goto rtmp_destroy;
if (flv) {
// flv header
char header[9];
// 3bytes, signature, "FLV",
header[0] = 'F';
header[1] = 'L';
header[2] = 'V';
// 1bytes, version, 0x01,
header[3] = 0x01;
// 1bytes, flags, UB[5] 0, UB[1] audio present, UB[1] 0, UB[1] video present.
header[4] = 0x03; // audio + video.
// 4bytes, dataoffset
header[5] = 0x00;
header[6] = 0x00;
header[7] = 0x00;
header[8] = 0x09;
if (srs_flv_write_header(flv, header) != 0) {
srs_human_trace("write flv header failed.");
goto rtmp_destroy;
}
}
for (;;) {
@ -105,9 +270,11 @@ int main(int argc, char** argv)
goto rtmp_destroy;
}
if (srs_flv_write_tag(flv, type, timestamp, data, size) != 0) {
srs_human_trace("dump rtmp packet failed.");
goto rtmp_destroy;
if (flv) {
if (srs_flv_write_tag(flv, type, timestamp, data, size) != 0) {
srs_human_trace("dump rtmp packet failed.");
goto rtmp_destroy;
}
}
free(data);
@ -115,7 +282,9 @@ int main(int argc, char** argv)
rtmp_destroy:
srs_rtmp_destroy(rtmp);
srs_flv_close(flv);
if (flv) {
srs_flv_close(flv);
}
srs_human_trace("completed");
return 0;