Blame view

trunk/research/librtmp/srs_detect_rtmp.c 6.9 KB
winlin authored
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/*
The MIT License (MIT)

Copyright (c) 2013-2014 winlin

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
gcc srs_detect_rtmp.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_detect_rtmp
*/

#include <stdio.h>
#include <stdlib.h>

#include "../../objs/include/srs_librtmp.h"

int main(int argc, char** argv)
{
34
    int ret = 0;
winlin authored
35 36
    srs_rtmp_t rtmp;
    
winlin authored
37 38 39 40 41 42 43 44 45
    // time
    int64_t time_startup = srs_get_time_ms();
    int64_t time_dns_resolve = 0;
    int64_t time_socket_connect = 0;
    int64_t time_play_stream = 0;
    int64_t time_first_packet = 0;
    int64_t time_cleanup = 0;
    // delay = actual - expect time when quit.
    int delay = 0;
46 47 48 49
    // bytes
    int64_t bytes_nsend = 0;
    int time_duration = 0;
    int64_t bytes_nrecv = 0;
winlin authored
50
    
winlin authored
51 52
    // packet data
    int type, size;
53
    u_int32_t basetime = 0;
winlin authored
54 55 56
    u_int32_t timestamp = 0;
    char* data;
    
winlin authored
57 58 59 60 61 62
    // user options
    const char* rtmp_url = NULL;
    int duration = 0;
    int timeout = 0;
    
    if (argc <= 3) {
winlin authored
63
        printf("detect stream on RTMP server\n"
winlin authored
64
            "Usage: %s <rtmp_url> <duration> <timeout>\n"
winlin authored
65
            "   rtmp_url     RTMP stream url to play\n"
winlin authored
66 67
            "   duration     how long to play, in seconds, stream time.\n"
            "   timeout      how long to timeout, in seconds, system time.\n"
winlin authored
68
            "For example:\n"
winlin authored
69
            "   %s rtmp://127.0.0.1:1935/live/livestream 3 10\n",
winlin authored
70
            argv[0], argv[0]);
71
        ret = 1;
winlin authored
72 73 74 75
        exit(ret);
        return ret;
    }
    
winlin authored
76 77 78
    rtmp_url = argv[1];
    duration = atoi(argv[2]);
    timeout = atoi(argv[3]);
winlin authored
79 80 81 82
    
    printf("detect rtmp stream\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());
winlin authored
83 84 85 86
    printf("rtmp url: %s\n", rtmp_url);
    printf("duration: %ds, timeout:%ds\n", duration, timeout);
    
    if (duration <= 0 || timeout <= 0) {
87
        ret = 1;
88
        fprintf(stderr, "duration and timeout must be positive. ret=%d\n", ret);
89 90
        exit(ret);
        return ret;
winlin authored
91 92 93 94
    }
    
    rtmp = srs_rtmp_create(rtmp_url);
    
95
    if ((ret = __srs_dns_resolve(rtmp)) != 0) {
96
        fprintf(stderr, "dns resolve failed. ret=%d\n", ret);
winlin authored
97 98 99 100 101
        goto rtmp_destroy;
    }
    printf("dns resolve success\n");
    time_dns_resolve = srs_get_time_ms();
    
102
    if ((ret = __srs_connect_server(rtmp)) != 0) {
103
        fprintf(stderr, "socket connect failed. ret=%d\n", ret);
winlin authored
104 105 106 107
        goto rtmp_destroy;
    }
    printf("socket connect success\n");
    time_socket_connect = srs_get_time_ms();
winlin authored
108
    
109
    if ((ret = __srs_do_simple_handshake(rtmp)) != 0) {
110
        fprintf(stderr, "do simple handshake failed. ret=%d\n", ret);
winlin authored
111 112
        goto rtmp_destroy;
    }
winlin authored
113
    printf("do simple handshake success\n");
winlin authored
114
    
115
    if ((ret = srs_connect_app(rtmp)) != 0) {
116
        fprintf(stderr, "connect vhost/app failed. ret=%d\n", ret);
winlin authored
117 118 119 120
        goto rtmp_destroy;
    }
    printf("connect vhost/app success\n");
    
121
    if ((ret = srs_play_stream(rtmp)) != 0) {
122
        fprintf(stderr, "play stream failed. ret=%d\n", ret);
winlin authored
123 124 125
        goto rtmp_destroy;
    }
    printf("play stream success\n");
winlin authored
126
    time_play_stream = srs_get_time_ms();
winlin authored
127 128
    
    for (;;) {
129
        if ((ret = srs_read_packet(rtmp, &type, &timestamp, &data, &size)) != 0) {
130
            fprintf(stderr, "read packet failed. ret=%d\n", ret);
winlin authored
131 132 133 134
            goto rtmp_destroy;
        }
        printf("got packet: type=%s, time=%d, size=%d\n", srs_type2string(type), timestamp, size);
        
135 136 137 138 139 140 141
        if (SRS_RTMP_TYPE_VIDEO == type || SRS_RTMP_TYPE_AUDIO == type) {
            if (time_first_packet <= 0) {
                time_first_packet = srs_get_time_ms();
            }
            if (basetime <= 0) {
                basetime = timestamp;
            }
winlin authored
142 143
        }
        
winlin authored
144
        free(data);
winlin authored
145 146 147 148 149 150
        
        if (srs_get_time_ms() - time_startup > timeout * 1000) {
            printf("timeout, terminate.\n");
            goto rtmp_destroy;
        }
        
151
        if ((timestamp - basetime) > duration * 1000) {
winlin authored
152 153 154
            printf("duration exceed, terminate.\n");
            goto rtmp_destroy;
        }
winlin authored
155 156 157
    }
    
rtmp_destroy:
158 159 160
    bytes_nsend = srs_get_nsend_bytes(rtmp);
    bytes_nrecv = srs_get_nrecv_bytes(rtmp);
    
winlin authored
161
    srs_rtmp_destroy(rtmp);
winlin authored
162
    time_cleanup = srs_get_time_ms();
163
    time_duration = (int)(time_cleanup - time_startup);
winlin authored
164 165 166
    
    // print result to stderr.
    fprintf(stderr, "{"
167
        "\"%s\":%d, " //#0
winlin authored
168 169 170 171 172 173 174
        "\"%s\":%d, " //#1
        "\"%s\":%d, " // #2
        "\"%s\":%d, " // #3
        "\"%s\":%d, " // #4
        "\"%s\":%d, " // #5
        "\"%s\":%d, " // #6
        "\"%s\":%d, " // #7
175
        "\"%s\":%d, " // #8
176 177
        "\"%s\":%d, " // #9
        "\"%s\":%d, " // #10
178
        "%s,%s,%s,%s}",
179
        "code", ret, //#0
winlin authored
180
        // total = dns + tcp_connect + start_play + first_packet + last_packet
181
        "total", time_duration, //#1
winlin authored
182 183 184 185 186
        "dns", (int)(time_dns_resolve - time_startup), //#2
        "tcp_connect", (int)(time_socket_connect - time_dns_resolve), //#3
        "start_play", (int)(time_play_stream - time_socket_connect), //#4
        "first_packet", (int)(time_first_packet - time_play_stream), //#5
        "last_packet", (int)(time_cleanup - time_first_packet), //#6
187
        "stream", (int)(timestamp - basetime), //#7
winlin authored
188
        // expect = time_cleanup - time_first_packet
189
        // actual = stream
winlin authored
190
        // delay = actual - expect
191
        "delay", (int)(timestamp - basetime - (time_cleanup - time_first_packet)), //#8
192 193
        "publish_kbps", (int)((time_duration <= 0)? 0:(bytes_nsend * 8 / time_duration)), //#9
        "play_kbps", (int)((time_duration <= 0)? 0:(bytes_nrecv * 8 / time_duration)), //#10
winlin authored
194
        // unit in ms.
195 196
        "\"unit\": \"ms\"",
        "\"remark0\": \"total = dns + tcp_connect + start_play + first_packet + last_packet\"",
197 198
        "\"remark1\": \"delay = stream - (time_cleanup - time_first_packet)\"",
        "\"remark2\": \"if code is not 0, user must ignore all data\""
winlin authored
199 200
    );
    printf("\n");
winlin authored
201
    
202
    return ret;
winlin authored
203
}