51 #define APP_MAX_LENGTH 1024 
   52 #define PLAYPATH_MAX_LENGTH 512 
   53 #define TCURL_MAX_LENGTH 1024 
   54 #define FLASHVER_MAX_LENGTH 64 
   55 #define RTMP_PKTDATA_DEFAULT_SIZE 4096 
   56 #define RTMP_HEADER 11 
  135 #define PLAYER_KEY_OPEN_PART_LEN 30    
  138     'G', 
'e', 
'n', 
'u', 
'i', 
'n', 
'e', 
' ', 
'A', 
'd', 
'o', 
'b', 
'e', 
' ',
 
  139     'F', 
'l', 
'a', 
's', 
'h', 
' ', 
'P', 
'l', 
'a', 
'y', 
'e', 
'r', 
' ', 
'0', 
'0', 
'1',
 
  141     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
 
  142     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
 
  143     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
 
  146 #define SERVER_KEY_OPEN_PART_LEN 36    
  149     'G', 
'e', 
'n', 
'u', 
'i', 
'n', 
'e', 
' ', 
'A', 
'd', 
'o', 
'b', 
'e', 
' ',
 
  150     'F', 
'l', 
'a', 
's', 
'h', 
' ', 
'M', 
'e', 
'd', 
'i', 
'a', 
' ',
 
  151     'S', 
'e', 
'r', 
'v', 
'e', 
'r', 
' ', 
'0', 
'0', 
'1',
 
  153     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
 
  154     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
 
  155     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
 
  191                                char **tracked_method)
 
  266     if (param[0] && param[1] == 
':') {
 
  269     } 
else if (param[0] == 
'N' && param[1] && param[2] == 
':') {
 
  272         value = strchr(field, 
':');
 
  373         char *param = rt->
conn;
 
  378             param += strspn(param, 
" ");
 
  381             sep = strchr(param, 
' ');
 
  435     if (strcmp(command, 
"connect")) {
 
  446                                  "app", tmpstr, 
sizeof(tmpstr));
 
  449     if (!ret && strcmp(tmpstr, rt->
app))
 
  472     bytestream_put_byte(&p, 2); 
 
  486     bytestream_put_be16(&p, 0); 
 
  487     bytestream_put_be32(&p, 0);
 
  718     bytestream_put_be16(&p, 3);
 
  839     if (ppkt->
size < 6) {
 
  850     bytestream_put_be16(&p, 7);
 
  871     bytestream_put_be16(&p, 27);
 
  937                                   const char *subscribe)
 
  944                                      0, 27 + strlen(subscribe))) < 0)
 
  982     int i, digest_pos = 0;
 
  984     for (i = 0; i < 4; i++)
 
  985         digest_pos += buf[i + off];
 
  986     digest_pos = digest_pos % mod_val + add_val;
 
 1001     int ret, digest_pos;
 
 1027     int ret, digest_pos;
 
 1037     if (!memcmp(digest, buf + digest_pos, 32))
 
 1050                "Hash of the decompressed SWF file is not 32 bytes long.\n");
 
 1055     bytestream_put_byte(&p, 1);
 
 1056     bytestream_put_byte(&p, 1);
 
 1057     bytestream_put_be32(&p, rt->
swfsize);
 
 1058     bytestream_put_be32(&p, rt->
swfsize);
 
 1067 static int rtmp_uncompress_swfplayer(
uint8_t *in_data, int64_t in_size,
 
 1070     z_stream zs = { 0 };
 
 1075     zs.avail_in = in_size;
 
 1076     zs.next_in  = in_data;
 
 1077     ret = inflateInit(&zs);
 
 1084         zs.avail_out = 
sizeof(tmp_buf);
 
 1085         zs.next_out  = tmp_buf;
 
 1087         ret = 
inflate(&zs, Z_NO_FLUSH);
 
 1088         if (ret != Z_OK && ret != Z_STREAM_END) {
 
 1093         size = 
sizeof(tmp_buf) - zs.avail_out;
 
 1094         if (!(ptr = 
av_realloc(*out_data, *out_size + size))) {
 
 1100         memcpy(*out_data + *out_size, tmp_buf, size);
 
 1102     } 
while (zs.avail_out == 0);
 
 1146     if (!memcmp(in_data, 
"CWS", 3)) {
 
 1153         memcpy(out_data, in_data, 8);
 
 1157         if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
 
 1158                                              &out_data, &out_size)) < 0)
 
 1162                "Zlib is required for decompressing the SWF player file.\n");
 
 1175                                    "Genuine Adobe Flash Player 001", 30,
 
 1210     int server_pos, client_pos;
 
 1221     if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
 
 1261            serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
 
 1263     if (rt->
is_input && serverdata[5] >= 3) {
 
 1295                                   0, digest, 32, signature);
 
 1299         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
 
 1303                                                    tosend + 1, type)) < 0)
 
 1325                                   tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
 
 1329         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
 
 1332                                  RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
 
 1338                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
 
 1341         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
 
 1347         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
 
 1351                             tosend + 1, 1)) < 0)
 
 1354             if (serverdata[0] == 9) {
 
 1365         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
 
 1376                                   uint32_t *second_int, 
char *arraydata,
 
 1387                " not following standard\n", (
int)inoutsize);
 
 1391     *first_int  = 
AV_RB32(arraydata);
 
 1392     *second_int = 
AV_RB32(arraydata + 4);
 
 1397                                uint32_t second_int, 
char *arraydata, 
int size)
 
 1401     AV_WB32(arraydata, first_int);
 
 1402     AV_WB32(arraydata + 4, second_int);
 
 1420     uint32_t hs_my_epoch;
 
 1430     if (inoutsize <= 0) {
 
 1435     if (buffer[0] != 3) {
 
 1441                "Unable to write answer - RTMP S0\n");
 
 1453     hs_my_epoch = hs_epoch;
 
 1479     if (temp != hs_my_epoch)
 
 1481                "Erroneous C2 Message epoch does not match up with C1 epoch\n");
 
 1482     if (memcmp(buffer + 8, hs_s1 + 8,
 
 1485                "Erroneous C2 Message random does not match up\n");
 
 1495     if (pkt->
size < 4) {
 
 1497                "Too short chunk size change packet (%d)\n",
 
 1528     if (pkt->
size < 2) {
 
 1536         if ((ret = 
gen_pong(s, rt, pkt)) < 0)
 
 1538     } 
else if (t == 26) {
 
 1554     if (pkt->
size < 4) {
 
 1556                "Client bandwidth report packet is less than 4 bytes long (%d)\n",
 
 1578     if (pkt->
size < 4) {
 
 1580                "Too short server bandwidth report packet (%d)\n",
 
 1597                          const char *opaque, 
const char *challenge)
 
 1625              "?authmod=%s&user=%s&challenge=%s&response=%s",
 
 1626              "adobe", user, challenge2, hashstr);
 
 1629                     "&opaque=%s", opaque);
 
 1638     char hashstr1[33], hashstr2[33];
 
 1639     const char *realm = 
"live";
 
 1640     const char *method = 
"publish";
 
 1641     const char *qop = 
"auth";
 
 1642     const char *nc = 
"00000001";
 
 1658     hashstr1[32] = 
'\0';
 
 1664     if (!strchr(rt->
app, 
'/'))
 
 1668     hashstr2[32] = 
'\0';
 
 1687              "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
 
 1688              "llnw", user, nonce, cnonce, nc, hashstr1);
 
 1697     char buf[300], *ptr, authmod[15];
 
 1699     const char *user = 
"", *salt = 
"", *opaque = 
NULL,
 
 1702     if (!(cptr = strstr(desc, 
"authmod=adobe")) &&
 
 1703         !(cptr = strstr(desc, 
"authmod=llnw"))) {
 
 1705                "Unknown connect error (unsupported authentication method?)\n");
 
 1708     cptr += strlen(
"authmod=");
 
 1709     while (*cptr && *cptr != 
' ' && i < 
sizeof(authmod) - 1)
 
 1710         authmod[i++] = *cptr++;
 
 1718     if (strstr(desc, 
"?reason=authfailed")) {
 
 1721     } 
else if (strstr(desc, 
"?reason=nosuchuser")) {
 
 1733     if (strstr(desc, 
"code=403 need auth")) {
 
 1735                  "?authmod=%s&user=%s", authmod, rt->
username);
 
 1739     if (!(cptr = strstr(desc, 
"?reason=needauth"))) {
 
 1748         char *next  = strchr(ptr, 
'&');
 
 1749         char *
value = strchr(ptr, 
'=');
 
 1754             if (!strcmp(ptr, 
"user")) {
 
 1756             } 
else if (!strcmp(ptr, 
"salt")) {
 
 1758             } 
else if (!strcmp(ptr, 
"opaque")) {
 
 1760             } 
else if (!strcmp(ptr, 
"challenge")) {
 
 1762             } 
else if (!strcmp(ptr, 
"nonce")) {
 
 1773     if (!strcmp(authmod, 
"adobe")) {
 
 1774         if ((ret = 
do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
 
 1789     char *tracked_method = 
NULL;
 
 1798                                 "description", tmpstr, 
sizeof(tmpstr))) {
 
 1799         if (tracked_method && (!strcmp(tracked_method, 
"_checkbw")      ||
 
 1800                                !strcmp(tracked_method, 
"releaseStream") ||
 
 1801                                !strcmp(tracked_method, 
"FCSubscribe")   ||
 
 1802                                !strcmp(tracked_method, 
"FCPublish"))) {
 
 1806         } 
else if (tracked_method && !strcmp(tracked_method, 
"getStreamLength")) {
 
 1809         } 
else if (tracked_method && !strcmp(tracked_method, 
"connect")) {
 
 1817         av_log(s, level, 
"Server error: %s\n", tmpstr);
 
 1839     bytestream2_put_be16(&pbc, 0);          
 
 1851                         const char *status, 
const char *filename)
 
 1855     char statusmsg[128];
 
 1878     snprintf(statusmsg, 
sizeof(statusmsg),
 
 1879              "%s is now published", filename);
 
 1923     if (!strcmp(command, 
"FCPublish") ||
 
 1924         !strcmp(command, 
"publish")) {
 
 1926                                  sizeof(filename), &stringlen);
 
 1932                        "Unable to find / in url %s, bad format\n",
 
 1937             if (strcmp(pchar, filename))
 
 1939                        " %s\n", filename, pchar);
 
 1944     if (!strcmp(command, 
"FCPublish")) {
 
 1953     } 
else if (!strcmp(command, 
"publish")) {
 
 1961     } 
else if (!strcmp(command, 
"play")) {
 
 1979         if (!strcmp(command, 
"createStream")) {
 
 2018     if (strcmp(strbuffer, 
"_result"))
 
 2030         *number = numbuffer;
 
 2038     char *tracked_method = 
NULL;
 
 2044     if (!tracked_method) {
 
 2049     if (!strcmp(tracked_method, 
"connect")) {
 
 2070             } 
else if (rt->
live == -1) {
 
 2075     } 
else if (!strcmp(tracked_method, 
"createStream")) {
 
 2087             if (rt->
live != -1) {
 
 2096     } 
else if (!strcmp(tracked_method, 
"getStreamLength")) {
 
 2115     for (i = 0; i < 2; i++) {
 
 2123     if (!t && !strcmp(tmpstr, 
"error")) {
 
 2125                                    "description", tmpstr, 
sizeof(tmpstr));
 
 2126         if (t || !tmpstr[0])
 
 2128                                        tmpstr, 
sizeof(tmpstr));
 
 2137     if (!t && !strcmp(tmpstr, 
"NetStream.Play.UnpublishNotify")) rt->
state = 
STATE_STOPPED;
 
 2191     return old_flv_size;
 
 2196     int old_flv_size, ret;
 
 2199     const int size      = pkt->
size - skip;
 
 2216     bytestream2_put_byte(&pbc, pkt->
type);
 
 2217     bytestream2_put_be24(&pbc, size);
 
 2218     bytestream2_put_be24(&pbc, ts);
 
 2219     bytestream2_put_byte(&pbc, ts >> 24);
 
 2220     bytestream2_put_be24(&pbc, 0);
 
 2231     char statusmsg[128];
 
 2232     int stringlen, ret, skip = 0;
 
 2240     if (!strcmp(commandbuffer, 
"onMetaData")) {
 
 2260                 if (!strcmp(statusmsg, 
"videocodecid")) {
 
 2263                 if (!strcmp(statusmsg, 
"audiocodecid")) {
 
 2273     if (!strcmp(commandbuffer, 
"@setDataFrame")) {
 
 2276                                  sizeof(statusmsg), &stringlen);
 
 2298     switch (pkt->
type) {
 
 2337     int ret, old_flv_size, 
type;
 
 2341     uint32_t ts, cts, 
pts = 0;
 
 2357         type = bytestream_get_byte(&next);
 
 2358         size = bytestream_get_be24(&next);
 
 2359         cts  = bytestream_get_be24(&next);
 
 2360         cts |= bytestream_get_byte(&next) << 24;
 
 2365         if (size + 3 + 4 > pkt->
data + pkt->
size - next)
 
 2367         bytestream_put_byte(&p, type);
 
 2368         bytestream_put_be24(&p, size);
 
 2369         bytestream_put_be24(&p, ts);
 
 2370         bytestream_put_byte(&p, ts >> 24);
 
 2371         memcpy(p, next, size + 3 + 4);
 
 2374         next += size + 3 + 4;
 
 2378                                      "RTMP_PT_METADATA packet\n");
 
 2493     for (i = 0; i < 2; i++) {
 
 2531     memcpy(rt->
flv_data, old_flv_data, 13);
 
 2541     bytestream_put_be24(&p, 40); 
 
 2542     bytestream_put_be24(&p, 0);  
 
 2543     bytestream_put_be32(&p, 0);  
 
 2548     bytestream_put_be16(&p, 10);
 
 2553     bytestream_put_be32(&p, 1); 
 
 2556     bytestream_put_be16(&p, 8);
 
 2562     bytestream_put_be16(&p, 0); 
 
 2581     char proto[8], hostname[256], path[1024], auth[100], *fname;
 
 2582     char *old_app, *qmark, *
n, fname_buffer[1024];
 
 2594                  hostname, 
sizeof(hostname), &port,
 
 2597     n = strchr(path, 
' ');
 
 2600                "Detected librtmp style URL parameters, these aren't supported " 
 2601                "by the libavformat internal RTMP handler currently enabled. " 
 2602                "See the documentation for the correct way to pass parameters.\n");
 
 2607         char *ptr = strchr(auth, 
':');
 
 2615     if (rt->
listen && strcmp(proto, 
"rtmp")) {
 
 2620     if (!strcmp(proto, 
"rtmpt") || !strcmp(proto, 
"rtmpts")) {
 
 2621         if (!strcmp(proto, 
"rtmpts"))
 
 2626     } 
else if (!strcmp(proto, 
"rtmps")) {
 
 2631     } 
else if (!strcmp(proto, 
"rtmpe") || (!strcmp(proto, 
"rtmpte"))) {
 
 2632         if (!strcmp(proto, 
"rtmpte"))
 
 2633             av_dict_set(&opts, 
"ffrtmpcrypt_tunneling", 
"1", 1);
 
 2644                         "?listen&listen_timeout=%d",
 
 2683     qmark = strchr(path, 
'?');
 
 2684     if (qmark && strstr(qmark, 
"slist=")) {
 
 2688         fname = strstr(path, 
"slist=") + 6;
 
 2690         amp = strchr(fname, 
'&');
 
 2693                                                   sizeof(fname_buffer)));
 
 2694             fname = fname_buffer;
 
 2696     } 
else if (!strncmp(path, 
"/ondemand/", 10)) {
 
 2698         memcpy(rt->
app, 
"ondemand", 9);
 
 2700         char *next = *path ? path + 1 : path;
 
 2701         char *p = strchr(next, 
'/');
 
 2713             char *
c = strchr(p + 1, 
':');
 
 2714             fname = strchr(p + 1, 
'/');
 
 2715             if (!fname || (c && c < fname)) {
 
 2743             int len = strlen(fname);
 
 2744             if (!strchr(fname, 
':') && len >= 4 &&
 
 2745                 (!strcmp(fname + len - 4, 
".f4v") ||
 
 2746                  !strcmp(fname + len - 4, 
".mp4"))) {
 
 2749                 if (len >= 4 && !strcmp(fname + len - 4, 
".flv"))
 
 2750                     fname[len - 4] = 
'\0';
 
 2766                     port, 
"/%s", rt->
app);
 
 2806     } 
while (ret == 
AVERROR(EAGAIN));
 
 2816         for (i = 0; i < 2; i++)
 
 2878     int orig_size = 
size;
 
 2884         if (data_left >= size) {
 
 2889         if (data_left > 0) {
 
 2908            "Seek on stream index %d at timestamp %"PRId64
" with flags %08x\n",
 
 2909            stream_index, timestamp, flags);
 
 2910     if ((ret = 
gen_seek(s, rt, timestamp)) < 0) {
 
 2912                "Unable to send seek command on stream index %d at timestamp " 
 2913                "%"PRId64
" with flags %08x\n",
 
 2914                stream_index, timestamp, flags);
 
 2939     int size_temp = 
size;
 
 2940     int pktsize, pkttype, 
copy;
 
 2966             pkttype = bytestream_get_byte(&header);
 
 2967             pktsize = bytestream_get_be24(&header);
 
 2968             ts = bytestream_get_be24(&header);
 
 2969             ts |= bytestream_get_byte(&header) << 24;
 
 2970             bytestream_get_be24(&header);
 
 2990                                              pkttype, ts, pktsize)) < 0)
 
 3017                     if (!strcmp(commandbuffer, 
"onMetaData") ||
 
 3018                         !strcmp(commandbuffer, 
"|RtmpSampleAccess")) {
 
 3039     } 
while (buf_temp - buf < size);
 
 3057     } 
else if (ret < 0) {
 
 3059     } 
else if (ret == 1) {
 
 3077 #define OFFSET(x) offsetof(RTMPContext, x) 
 3078 #define DEC AV_OPT_FLAG_DECODING_PARAM 
 3079 #define ENC AV_OPT_FLAG_ENCODING_PARAM 
 3083     {
"rtmp_buffer", 
"Set buffer time in milliseconds. The default is 3000.", 
OFFSET(client_buffer_time), 
AV_OPT_TYPE_INT, {.i64 = 3000}, 0, INT_MAX, 
DEC|
ENC},
 
 3086     {
"rtmp_flush_interval", 
"Number of packets flushed in the same request (RTMPT only).", 
OFFSET(flush_interval), 
AV_OPT_TYPE_INT, {.i64 = 10}, 0, INT_MAX, 
ENC},
 
 3087     {
"rtmp_live", 
"Specify that the media is a live stream.", 
OFFSET(live), 
AV_OPT_TYPE_INT, {.i64 = -2}, INT_MIN, INT_MAX, 
DEC, 
"rtmp_live"},
 
 3091     {
"rtmp_pageurl", 
"URL of the web page in which the media was embedded. By default no value will be sent.", 
OFFSET(pageurl), 
AV_OPT_TYPE_STRING, {.str = 
NULL }, 0, 0, 
DEC},
 
 3093     {
"rtmp_subscribe", 
"Name of live stream to subscribe to. Defaults to rtmp_playpath.", 
OFFSET(subscribe), 
AV_OPT_TYPE_STRING, {.str = 
NULL }, 0, 0, 
DEC},
 
 3095     {
"rtmp_swfsize", 
"Size of the decompressed SWF file, required for SWFVerification.", 
OFFSET(swfsize), 
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, 
DEC},
 
 3099     {
"rtmp_listen", 
"Listen for incoming rtmp connections", 
OFFSET(listen), 
AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, 
DEC, 
"rtmp_listen" },
 
 3100     {
"listen",      
"Listen for incoming rtmp connections", 
OFFSET(listen), 
AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, 
DEC, 
"rtmp_listen" },
 
 3101     {
"timeout", 
"Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1",  
OFFSET(listen_timeout), 
AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, 
DEC, 
"rtmp_listen" },
 
 3105 #define RTMP_PROTOCOL(flavor)                    \ 
 3106 static const AVClass flavor##_class = {          \ 
 3107     .class_name = #flavor,                       \ 
 3108     .item_name  = av_default_item_name,          \ 
 3109     .option     = rtmp_options,                  \ 
 3110     .version    = LIBAVUTIL_VERSION_INT,         \ 
 3113 URLProtocol ff_##flavor##_protocol = {           \ 
 3115     .url_open       = rtmp_open,                 \ 
 3116     .url_read       = rtmp_read,                 \ 
 3117     .url_read_seek  = rtmp_seek,                 \ 
 3118     .url_read_pause = rtmp_pause,                \ 
 3119     .url_write      = rtmp_write,                \ 
 3120     .url_close      = rtmp_close,                \ 
 3121     .priv_data_size = sizeof(RTMPContext),       \ 
 3122     .flags          = URL_PROTOCOL_FLAG_NETWORK, \ 
 3123     .priv_data_class= &flavor##_class,           \ 
static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
Generate report on bytes read so far and send it to the server. 
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components. 
static int gen_swf_verification(URLContext *s, RTMPContext *rt)
Generate SWF verification message and send it to the server. 
int ff_amf_match_string(const uint8_t *data, int size, const char *str)
Match AMF string with a NULL-terminated string. 
int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket **prev_pkt, int *nb_prev_pkt, uint8_t hdr)
Read internal RTMP packet sent by the server. 
static int rtmp_read(URLContext *s, uint8_t *buf, int size)
int live
0: recorded, -1: live, -2: both 
#define AVERROR_INVALIDDATA
Invalid data found when processing input. 
int ff_amf_read_null(GetByteContext *bc)
Read AMF NULL value. 
static int gen_pause(URLContext *s, RTMPContext *rt, int pause, uint32_t timestamp)
Generate a pause packet that either pauses or unpauses the current stream. 
uint8_t flv_header[RTMP_HEADER]
partial incoming flv packet header 
ptrdiff_t const GLvoid * data
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
AVHMAC * av_hmac_alloc(enum AVHMACType type)
Allocate an AVHMAC context. 
static int handle_invoke(URLContext *s, RTMPPacket *pkt)
int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket **prev_pkt, int *nb_prev_pkt)
Read RTMP packet sent by the server. 
#define AV_LOG_WARNING
Something somehow does not look correct. 
static int gen_check_bw(URLContext *s, RTMPContext *rt)
Generate check bandwidth message and send it to the server. 
static const uint8_t rtmp_server_key[]
Key used for RTMP server digest signing. 
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h. 
#define RTMPS_DEFAULT_PORT
int is_streamed
true if streamed (no seek possible), default = false 
static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt, const char *subscribe)
void ff_amf_write_field_name(uint8_t **dst, const char *str)
Write string used as field name in AMF object to buffer. 
int flv_header_bytes
number of initialized bytes in flv_header 
AVIOInterruptCB interrupt_callback
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
#define AVIO_FLAG_READ
read-only 
#define AVIO_FLAG_WRITE
write-only 
int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
Calculate number of bytes taken by first AMF entry in data. 
static int gen_create_stream(URLContext *s, RTMPContext *rt)
Generate 'createStream' call and send it to the server. 
static av_always_inline uint64_t av_double2int(double f)
Reinterpret a double as a 64-bit integer. 
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags)
URLContext * stream
TCP stream used in interactions with RTMP server. 
int in_chunk_size
size of the chunks incoming RTMP packets are divided into 
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
double duration
Duration of the stream in seconds as returned by the server (only valid if non-zero) ...
int skip_bytes
number of bytes to skip from the input FLV stream in the next write call 
uint32_t last_bytes_read
number of bytes read last reported to server 
static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
rtmp handshake server side 
void av_md5_update(AVMD5 *ctx, const uint8_t *src, int len)
Update hash value. 
RTMPPacketType type
packet payload type 
int flv_nb_packets
number of flv packets published 
static const char signature[]
struct AVMD5 * av_md5_alloc(void)
Allocate an AVMD5 context. 
int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap, const uint8_t *key, int keylen, uint8_t *dst)
Calculate HMAC-SHA2 digest for RTMP handshake packets. 
static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
#define RTMP_DEFAULT_PORT
uint32_t extra
probably an additional channel ID used during streaming data 
ClientState state
current state 
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development. 
static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
Generate 'FCUnpublish' call and send it to the server. 
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
#define RTMP_PKTDATA_DEFAULT_SIZE
TrackedMethod * tracked_methods
tracked methods buffer 
double strtod(const char *, char **)
void ff_amf_write_string(uint8_t **dst, const char *str)
Write string in AMF format to buffer. 
static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord)
int ff_rtmpe_compute_secret_key(URLContext *h, const uint8_t *serverdata, const uint8_t *clientdata, int type)
Compute the shared secret key and initialize the RC4 encryption. 
void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
Print information and contents of RTMP packet. 
int nb_invokes
keeps track of invoke messages 
int out_chunk_size
size of the chunks outgoing RTMP packets are divided into 
#define AVERROR_EOF
End of file. 
void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len)
Hash data with the HMAC. 
int flv_size
current buffer size 
#define AV_LOG_VERBOSE
Detailed information. 
int listen_timeout
listen timeout to wait for new connections 
int flush_interval
number of packets flushed in the same request (RTMPT only) 
static void copy(LZOContext *c, int cnt)
Copies bytes from input to output buffer with checking. 
char * swfverify
URL to player swf file, compute hash/size automatically. 
static int rtmp_handshake(URLContext *s, RTMPContext *rt)
Perform handshake with the server by means of exchanging pseudorandom data signed with HMAC-SHA2 dige...
int encrypted
use an encrypted connection (RTMPE only) 
static const uint8_t header[24]
int ff_rtmpe_gen_pub_key(URLContext *h, uint8_t *buf)
Initialize the Diffie-Hellmann context and generate the public key. 
int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val, int add_val)
Calculate digest position for RTMP handshake packets. 
void ff_amf_write_object_end(uint8_t **dst)
Write marker for end of AMF object to buffer. 
char * conn
append arbitrary AMF data to the Connect message 
received a play command (for output) 
static void del_tracked_method(RTMPContext *rt, int index)
static int rtmp_validate_digest(uint8_t *buf, int off)
Verify that the received server response has the expected digest value. 
int size
packet payload size 
static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
void ff_amf_write_bool(uint8_t **dst, int val)
Write boolean value in AMF format to buffer. 
static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt, const char *opaque, const char *challenge)
static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
Put HMAC-SHA2 digest of packet data (except for the bytes where this digest will be stored) into that...
static int write_status(URLContext *s, RTMPPacket *pkt, const char *status, const char *filename)
static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered. 
char * pageurl
url of the web page 
client has started the seek operation. Back on STATE_PLAYING when the time comes 
static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
static int inject_fake_duration_metadata(RTMPContext *rt)
Insert a fake onMetadata packet into the FLV stream to notify the FLV demuxer about the duration of t...
const char * protocol_whitelist
char * flashver
version of the flash plugin 
static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
ClientState
RTMP protocol handler state. 
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
char * swfurl
url of the swf player 
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers. 
#define PLAYER_KEY_OPEN_PART_LEN
length of partial key used for first client digest signing 
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
Generate 'FCPublish' call and send it to the server. 
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
static int gen_delete_stream(URLContext *s, RTMPContext *rt)
Generate 'deleteStream' call and send it to the server. 
char * playpath
stream identifier to play (with possible "mp4:" prefix) 
int ff_amf_get_string(GetByteContext *bc, uint8_t *str, int strsize, int *length)
Get AMF string value. 
client has not done anything yet 
static const uint8_t offset[127][2]
char * av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
Encode data to base64 and null-terminate. 
static void free_tracked_methods(RTMPContext *rt)
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst. 
int tracked_methods_size
size of the tracked methods buffer 
static int rtmp_pause(URLContext *s, int pause)
#define RTMP_PROTOCOL(flavor)
client has performed handshake 
static int gen_play(URLContext *s, RTMPContext *rt)
Generate 'play' call and send it to the server, then ping the server to start actual playing...
const uint8_t * buffer_end
static av_always_inline void bytestream2_skip_p(PutByteContext *p, unsigned int size)
#define PLAYPATH_MAX_LENGTH
int swfhash_len
length of the SHA256 hash 
static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
Parse received packet and possibly perform some action depending on the packet contents. 
#define AV_BASE64_SIZE(x)
Calculate the output size needed to base64-encode x bytes to a null-terminated string. 
client has started sending multimedia data to server (for output) 
void ff_rtmp_packet_destroy(RTMPPacket *pkt)
Free RTMP packet. 
static int gen_publish(URLContext *s, RTMPContext *rt)
Generate 'publish' call and send it to the server. 
GLsizei GLboolean const GLfloat * value
client has started receiving multimedia data from server 
void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen)
Initialize an AVHMAC context with an authentication key. 
int client_buffer_time
client buffer time in ms 
client FCPublishing stream (for output) 
int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end, const uint8_t *name, uint8_t *dst, int dst_size)
Retrieve value of given AMF object field in string form. 
static int rtmp_close(URLContext *h)
int nb_streamid
The next stream id to return on createStream calls. 
#define RTMP_CLIENT_PLATFORM
emulated Flash client version - 9.0.124.2 on Linux 
int has_video
presence of video data 
static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
Generate ping reply and send it to the server. 
static int add_tracked_method(RTMPContext *rt, const char *name, int id)
int is_input
input/output flag 
static const uint8_t rtmp_player_key[]
Client key used for digest signing. 
received a publish command (for input) 
static int rtmp_send_hs_packet(RTMPContext *rt, uint32_t first_int, uint32_t second_int, char *arraydata, int size)
static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp, int flags)
int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, int chunk_size, RTMPPacket **prev_pkt_ptr, int *nb_prev_pkt)
Send RTMP packet to the server. 
static int gen_get_stream_length(URLContext *s, RTMPContext *rt)
Generate 'getStreamLength' call and send it to the server. 
static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, uint8_t *dst, unsigned int size)
static int gen_buffer_time(URLContext *s, RTMPContext *rt)
Generate client buffer time and send it to the server. 
static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, const uint8_t *src, unsigned int size)
the broadcast has been stopped 
char * swfhash
SHA256 hash of the decompressed SWF file (32 bytes) 
char swfverification[42]
hash of the SWF verification 
int nb_tracked_methods
number of tracked methods 
offset must point to a pointer immediately followed by an int for the length 
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
#define AV_LOG_INFO
Standard information. 
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
int flv_off
number of bytes read from current buffer 
char * av_strdup(const char *s)
Duplicate the string s. 
static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode. 
uint32_t bytes_read
number of bytes read from server 
static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
void av_md5_init(AVMD5 *ctx)
Initialize MD5 hashing. 
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG. 
uint32_t last_timestamp
last timestamp received in a packet 
char * subscribe
name of live stream to subscribe 
void ff_rtmpe_encrypt_sig(URLContext *h, uint8_t *sig, const uint8_t *digest, int type)
Encrypt the signature. 
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag 
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry. 
channel for sending server control messages 
static int gen_connect(URLContext *s, RTMPContext *rt)
Generate 'connect' call and send it to the server. 
static int gen_release_stream(URLContext *s, RTMPContext *rt)
Generate 'releaseStream' call and send it to the server. 
Describe the class of an AVClass context structure. 
static int write_begin(URLContext *s)
static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset, char **tracked_method)
int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type, int timestamp, int size)
Create new RTMP packet with given attributes. 
int ff_rtmpe_update_keystream(URLContext *h)
Update the keystream and set RC4 keys for encryption. 
int ff_amf_read_number(GetByteContext *bc, double *val)
Read AMF number value. 
static int handle_notify(URLContext *s, RTMPPacket *pkt)
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
int channel_id
RTMP channel ID (nothing to do with audio/video channels though) 
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
RTMPPacket out_pkt
rtmp packet, created from flv a/v or metadata (for output) 
char * tcurl
url of the target stream 
static int handle_connect_error(URLContext *s, const char *desc)
void av_md5_final(AVMD5 *ctx, uint8_t *dst)
Finish hashing and output digest value. 
int listen
listen mode flag 
int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen)
Finish hashing and output the HMAC digest. 
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes...
static int rtmp_receive_hs_packet(RTMPContext *rt, uint32_t *first_int, uint32_t *second_int, char *arraydata, int size)
static int64_t pts
Global timestamp for the audio frames. 
int ffurl_close(URLContext *h)
#define SERVER_KEY_OPEN_PART_LEN
length of partial key used for first server digest signing 
channel for network-related messages (bandwidth report, ping, etc) 
static int gen_server_bw(URLContext *s, RTMPContext *rt)
Generate server bandwidth message and send it to the server. 
static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
void ff_amf_write_null(uint8_t **dst)
Write AMF NULL value to buffer. 
uint32_t timestamp
packet full timestamp 
#define RTMP_HANDSHAKE_PACKET_SIZE
#define FLASHVER_MAX_LENGTH
uint8_t * data
packet payload 
static int rtmp_open(URLContext *s, const char *uri, int flags)
Open RTMP connection and verify that the stream can be played. 
int stream_id
ID assigned by the server for the stream. 
int has_audio
presence of audio data 
RTMPPacket * prev_pkt[2]
packet history used when reading and sending packets ([0] for reading, [1] for writing) ...
int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
Change the position that will be used by the next read/write operation on the resource accessed by h...
char * app
name of application 
void * av_realloc(void *ptr, size_t size)
Allocate or reallocate a block of memory. 
int av_reallocp(void *ptr, size_t size)
Allocate or reallocate a block of memory. 
int ffurl_read_complete(URLContext *h, unsigned char *buf, int size)
Read as many bytes as possible (up to size), calling the read function multiple times if necessary...
static int rtmp_calc_swfhash(URLContext *s)
char * filename
specified URL 
void av_hmac_free(AVHMAC *c)
Free an AVHMAC context. 
int ff_rtmp_check_alloc_array(RTMPPacket **prev_pkt, int *nb_prev_pkt, int channel)
Enlarge the prev_pkt array to fit the given channel. 
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
#define AVERROR_UNKNOWN
Unknown error, typically from an external library. 
int ff_amf_read_string(GetByteContext *bc, uint8_t *str, int strsize, int *length)
Read AMF string value. 
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
void ff_amf_write_number(uint8_t **dst, double val)
Write number in AMF format to buffer. 
static const AVOption rtmp_options[]
static int get_packet(URLContext *s, int for_header)
Interact with the server by receiving and sending RTMP packets until there is some significant data (...
static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
uint8_t * flv_data
buffer with data for demuxer 
static int read_connect(URLContext *s, RTMPContext *rt)
int received_metadata
Indicates if we have received metadata about the streams. 
static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
void ff_amf_write_object_start(uint8_t **dst)
Write marker for AMF object to buffer. 
int max_packet_size
if non zero, the stream is packetized with this max packet size 
int swfsize
size of the decompressed SWF file 
int nb_prev_pkt[2]
number of elements in prev_pkt 
structure for holding RTMP packets 
void ff_amf_write_string2(uint8_t **dst, const char *str1, const char *str2)
Write a string consisting of two parts in AMF format to a buffer. 
static int update_offset(RTMPContext *rt, int size)
unbuffered private I/O API 
invoke some stream action 
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions. 
static int handle_ping(URLContext *s, RTMPPacket *pkt)
int ffurl_read(URLContext *h, unsigned char *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf...
uint32_t client_report_size
number of bytes after which client should report to server 
int server_bw
server bandwidth 
static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt, uint8_t *buf)
static int read_number_result(RTMPPacket *pkt, double *number)
Read the AMF_NUMBER response ("_result") to a function call (e.g.