53 #define APP_MAX_LENGTH 128
54 #define PLAYPATH_MAX_LENGTH 256
55 #define TCURL_MAX_LENGTH 512
56 #define FLASHVER_MAX_LENGTH 64
57 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
128 #define PLAYER_KEY_OPEN_PART_LEN 30
130 static const uint8_t rtmp_player_key[] = {
131 'G',
'e',
'n',
'u',
'i',
'n',
'e',
' ',
'A',
'd',
'o',
'b',
'e',
' ',
132 'F',
'l',
'a',
's',
'h',
' ',
'P',
'l',
'a',
'y',
'e',
'r',
' ',
'0',
'0',
'1',
134 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
135 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
136 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
139 #define SERVER_KEY_OPEN_PART_LEN 36
141 static const uint8_t rtmp_server_key[] = {
142 'G',
'e',
'n',
'u',
'i',
'n',
'e',
' ',
'A',
'd',
'o',
'b',
'e',
' ',
143 'F',
'l',
'a',
's',
'h',
' ',
'M',
'e',
'd',
'i',
'a',
' ',
144 'S',
'e',
'r',
'v',
'e',
'r',
' ',
'0',
'0',
'1',
146 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
147 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
148 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
181 char **tracked_method)
257 if (param[0] && param[1] ==
':') {
260 }
else if (param[0] ==
'N' && param[1] && param[2] ==
':') {
263 value = strchr(field,
':');
269 if (!field || !value)
367 char *param = rt->
conn;
370 while (param !=
NULL) {
372 param += strspn(param,
" ");
375 sep = strchr(param,
' ');
418 if (strcmp(command,
"connect")) {
429 "app", tmpstr,
sizeof(tmpstr));
432 if (!ret && strcmp(tmpstr, rt->
app))
455 bytestream_put_byte(&p, 2);
469 bytestream_put_be16(&p, 0);
470 bytestream_put_be32(&p, 0);
677 bytestream_put_be16(&p, 3);
748 if (ppkt->
size < 6) {
759 bytestream_put_be16(&p, 7);
780 bytestream_put_be16(&p, 27);
846 const char *subscribe)
853 0, 27 + strlen(subscribe))) < 0)
877 memcpy(hmac_buf, key, keylen);
883 for (i = 0; i < 64; i++)
896 for (i = 0; i < 64; i++)
910 int i, digest_pos = 0;
912 for (i = 0; i < 4; i++)
913 digest_pos += buf[i + off];
914 digest_pos = digest_pos % mod_val + add_val;
965 if (!memcmp(digest, buf + digest_pos, 32))
978 "Hash of the decompressed SWF file is not 32 bytes long.\n");
983 bytestream_put_byte(&p, 1);
984 bytestream_put_byte(&p, 1);
985 bytestream_put_be32(&p, rt->
swfsize);
986 bytestream_put_be32(&p, rt->
swfsize);
995 static int rtmp_uncompress_swfplayer(
uint8_t *in_data, int64_t in_size,
996 uint8_t **out_data, int64_t *out_size)
1003 zs.avail_in = in_size;
1004 zs.next_in = in_data;
1005 ret = inflateInit(&zs);
1012 zs.avail_out =
sizeof(tmp_buf);
1013 zs.next_out = tmp_buf;
1015 ret = inflate(&zs, Z_NO_FLUSH);
1016 if (ret != Z_OK && ret != Z_STREAM_END) {
1021 size =
sizeof(tmp_buf) - zs.avail_out;
1022 if (!(ptr =
av_realloc(*out_data, *out_size + size))) {
1028 memcpy(*out_data + *out_size, tmp_buf, size);
1030 }
while (zs.avail_out == 0);
1042 int64_t in_size, out_size;
1073 if (!memcmp(in_data,
"CWS", 3)) {
1080 memcpy(out_data, in_data, 8);
1084 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1085 &out_data, &out_size)) < 0)
1089 "Zlib is required for decompressing the SWF player file.\n");
1102 "Genuine Adobe Flash Player 001", 30,
1137 int server_pos, client_pos;
1188 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1190 if (rt->
is_input && serverdata[5] >= 3) {
1222 0, digest, 32, signature);
1230 tosend + 1, type)) < 0)
1252 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1259 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1265 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1278 tosend + 1, 1)) < 0)
1281 if (serverdata[0] == 9) {
1303 uint32_t *second_int,
char *arraydata,
1314 " not following standard\n", (
int)inoutsize);
1318 *first_int =
AV_RB32(arraydata);
1319 *second_int =
AV_RB32(arraydata + 4);
1324 uint32_t second_int,
char *arraydata,
int size)
1328 AV_WB32(arraydata, first_int);
1329 AV_WB32(arraydata + 4, first_int);
1347 uint32_t hs_my_epoch;
1357 if (inoutsize <= 0) {
1362 if (buffer[0] != 3) {
1368 "Unable to write answer - RTMP S0\n");
1382 hs_my_epoch = hs_epoch;
1408 if (temp != hs_my_epoch)
1410 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1411 if (memcmp(buffer + 8, hs_s1 + 8,
1414 "Erroneous C2 Message random does not match up\n");
1424 if (pkt->
size < 4) {
1426 "Too short chunk size change packet (%d)\n",
1457 if (pkt->
size < 2) {
1465 if ((ret =
gen_pong(s, rt, pkt)) < 0)
1467 }
else if (t == 26) {
1483 if (pkt->
size < 4) {
1485 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1507 if (pkt->
size < 4) {
1509 "Too short server bandwidth report packet (%d)\n",
1526 const char *opaque,
const char *challenge)
1554 "?authmod=%s&user=%s&challenge=%s&response=%s",
1555 "adobe", user, challenge2, hashstr);
1558 "&opaque=%s", opaque);
1567 char hashstr1[33], hashstr2[33];
1568 const char *realm =
"live";
1569 const char *method =
"publish";
1570 const char *qop =
"auth";
1571 const char *nc =
"00000001";
1587 hashstr1[32] =
'\0';
1595 hashstr2[32] =
'\0';
1614 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1615 "llnw", user, nonce, cnonce, nc, hashstr1);
1624 char buf[300], *ptr, authmod[15];
1626 const char *user =
"", *salt =
"", *opaque =
NULL,
1629 if (!(cptr = strstr(desc,
"authmod=adobe")) &&
1630 !(cptr = strstr(desc,
"authmod=llnw"))) {
1632 "Unknown connect error (unsupported authentication method?)\n");
1635 cptr += strlen(
"authmod=");
1636 while (*cptr && *cptr !=
' ' && i <
sizeof(authmod) - 1)
1637 authmod[i++] = *cptr++;
1645 if (strstr(desc,
"?reason=authfailed")) {
1648 }
else if (strstr(desc,
"?reason=nosuchuser")) {
1660 if (strstr(desc,
"code=403 need auth")) {
1662 "?authmod=%s&user=%s", authmod, rt->
username);
1666 if (!(cptr = strstr(desc,
"?reason=needauth"))) {
1675 char *next = strchr(ptr,
'&');
1676 char *value = strchr(ptr,
'=');
1681 if (!strcmp(ptr,
"user")) {
1683 }
else if (!strcmp(ptr,
"salt")) {
1685 }
else if (!strcmp(ptr,
"opaque")) {
1687 }
else if (!strcmp(ptr,
"challenge")) {
1689 }
else if (!strcmp(ptr,
"nonce")) {
1695 if (!strcmp(authmod,
"adobe")) {
1696 if ((ret =
do_adobe_auth(rt, user, salt, challenge, opaque)) < 0)
1711 char *tracked_method =
NULL;
1720 "description", tmpstr,
sizeof(tmpstr))) {
1721 if (tracked_method && (!strcmp(tracked_method,
"_checkbw") ||
1722 !strcmp(tracked_method,
"releaseStream") ||
1723 !strcmp(tracked_method,
"FCSubscribe") ||
1724 !strcmp(tracked_method,
"FCPublish"))) {
1728 }
else if (tracked_method && !strcmp(tracked_method,
"connect")) {
1736 av_log(s, level,
"Server error: %s\n", tmpstr);
1749 char statusmsg[128];
1771 if (!strcmp(command,
"FCPublish") ||
1772 !strcmp(command,
"publish")) {
1774 sizeof(filename), &stringlen);
1780 "Unable to find / in url %s, bad format\n",
1785 if (strcmp(pchar, filename))
1787 " %s\n", filename, pchar);
1792 if (!strcmp(command,
"FCPublish")) {
1801 }
else if (!strcmp(command,
"publish")) {
1811 bytestream2_put_be16(&pbc, 0);
1838 snprintf(statusmsg,
sizeof(statusmsg),
1839 "%s is now published", filename);
1859 if (!strcmp(command,
"createStream")) {
1879 char *tracked_method =
NULL;
1885 if (!tracked_method) {
1890 if (!strcmp(tracked_method,
"connect")) {
1911 }
else if (rt->
live == -1) {
1916 }
else if (!strcmp(tracked_method,
"createStream")) {
1918 if (pkt->
data[10] || pkt->
data[19] != 5 || pkt->
data[20]) {
1948 for (i = 0; i < 2; i++) {
1956 if (!t && !strcmp(tmpstr,
"error")) {
1958 "description", tmpstr,
sizeof(tmpstr)))
1966 if (!t && !strcmp(tmpstr,
"NetStream.Play.UnpublishNotify")) rt->
state =
STATE_STOPPED;
2007 char statusmsg[128];
2014 unsigned datatowritelength;
2021 if (!strcmp(commandbuffer,
"@setDataFrame")) {
2022 datatowrite = gbc.
buffer;
2025 sizeof(statusmsg), &stringlen))
2027 if (strcmp(statusmsg,
"onMetaData")) {
2039 rt->
flv_size += datatowritelength + 15;
2042 rt->
flv_size = datatowritelength + 15;
2052 bytestream2_put_byte(&pbc, pkt->
type);
2053 bytestream2_put_be24(&pbc, datatowritelength);
2054 bytestream2_put_be24(&pbc, ts);
2055 bytestream2_put_byte(&pbc, ts >> 24);
2056 bytestream2_put_be24(&pbc, 0);
2058 bytestream2_put_be32(&pbc, 0);
2077 switch (pkt->
type) {
2079 av_dlog(s,
"received bytes read report\n");
2132 uint32_t ts, cts, pts=0;
2187 bytestream_put_byte(&p, rpkt.
type);
2188 bytestream_put_be24(&p, rpkt.
size);
2189 bytestream_put_be24(&p, ts);
2190 bytestream_put_byte(&p, ts >> 24);
2191 bytestream_put_be24(&p, 0);
2193 bytestream_put_be32(&p, 0);
2212 while (next - rpkt.
data < rpkt.
size - 11) {
2214 size = bytestream_get_be24(&next);
2216 cts = bytestream_get_be24(&next);
2217 cts |= bytestream_get_byte(&next) << 24;
2222 bytestream_put_be24(&p, ts);
2223 bytestream_put_byte(&p, ts >> 24);
2224 next += size + 3 + 4;
2267 char proto[8], hostname[256], path[1024], auth[100], *fname;
2280 hostname,
sizeof(hostname), &port,
2284 char *ptr = strchr(auth,
':');
2292 if (rt->
listen && strcmp(proto,
"rtmp")) {
2297 if (!strcmp(proto,
"rtmpt") || !strcmp(proto,
"rtmpts")) {
2298 if (!strcmp(proto,
"rtmpts"))
2303 }
else if (!strcmp(proto,
"rtmps")) {
2308 }
else if (!strcmp(proto,
"rtmpe") || (!strcmp(proto,
"rtmpte"))) {
2309 if (!strcmp(proto,
"rtmpte"))
2310 av_dict_set(&opts,
"ffrtmpcrypt_tunneling",
"1", 1);
2321 "?listen&listen_timeout=%d",
2359 if (!strncmp(path,
"/ondemand/", 10)) {
2361 memcpy(rt->
app,
"ondemand", 9);
2363 char *next = *path ? path + 1 : path;
2364 char *p = strchr(next,
'/');
2370 char *c = strchr(p + 1,
':');
2371 fname = strchr(p + 1,
'/');
2372 if (!fname || (c && c < fname)) {
2389 int len = strlen(fname);
2397 if (!strchr(fname,
':') && len >= 4 &&
2398 (!strcmp(fname + len - 4,
".f4v") ||
2399 !strcmp(fname + len - 4,
".mp4"))) {
2401 }
else if (len >= 4 && !strcmp(fname + len - 4,
".flv")) {
2402 fname[len - 4] =
'\0';
2416 port,
"/%s", rt->
app);
2453 }
while (ret == EAGAIN);
2493 int orig_size =
size;
2499 if (data_left >= size) {
2504 if (data_left > 0) {
2520 int size_temp =
size;
2521 int pktsize, pkttype;
2523 const uint8_t *buf_temp = buf;
2545 pkttype = bytestream_get_byte(&header);
2546 pktsize = bytestream_get_be24(&header);
2547 ts = bytestream_get_be24(&header);
2548 ts |= bytestream_get_byte(&header) << 24;
2549 bytestream_get_be24(&header);
2562 pkttype, ts, pktsize)) < 0)
2592 }
while (buf_temp - buf < size);
2610 }
else if (ret < 0) {
2612 }
else if (ret == 1) {
2629 #define OFFSET(x) offsetof(RTMPContext, x)
2630 #define DEC AV_OPT_FLAG_DECODING_PARAM
2631 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2635 {
"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},
2638 {
"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},
2639 {
"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"},
2643 {
"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},
2645 {
"rtmp_subscribe",
"Name of live stream to subscribe to. Defaults to rtmp_playpath.",
OFFSET(subscribe),
AV_OPT_TYPE_STRING, {.str =
NULL }, 0, 0,
DEC},
2647 {
"rtmp_swfsize",
"Size of the decompressed SWF file, required for SWFVerification.",
OFFSET(swfsize),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX,
DEC},
2651 {
"rtmp_listen",
"Listen for incoming rtmp connections",
OFFSET(listen),
AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX,
DEC,
"rtmp_listen" },
2652 {
"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" },
2656 #define RTMP_PROTOCOL(flavor) \
2657 static const AVClass flavor##_class = { \
2658 .class_name = #flavor, \
2659 .item_name = av_default_item_name, \
2660 .option = rtmp_options, \
2661 .version = LIBAVUTIL_VERSION_INT, \
2664 URLProtocol ff_##flavor##_protocol = { \
2666 .url_open = rtmp_open, \
2667 .url_read = rtmp_read, \
2668 .url_write = rtmp_write, \
2669 .url_close = rtmp_close, \
2670 .priv_data_size = sizeof(RTMPContext), \
2671 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2672 .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_sha_final(AVSHA *ctx, uint8_t *digest)
Finish hashing and output digest value.
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.
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
static int rtmp_read(URLContext *s, uint8_t *buf, int size)
int live
0: recorded, -1: live, -2: both
int ff_amf_read_null(GetByteContext *bc)
Read AMF NULL value.
void av_sha_update(AVSHA *ctx, const uint8_t *data, unsigned int len)
Update hash value.
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
static int handle_invoke(URLContext *s, RTMPPacket *pkt)
int av_sha_init(AVSHA *ctx, int bits)
Initialize SHA-1 or SHA-2 hashing.
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
static int hash(int head, const int add)
Hash function adding character.
AVIOInterruptCB interrupt_callback
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
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.
struct RTMPContext RTMPContext
protocol handler context
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket *prev_pkt)
Read RTMP packet sent by the server.
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.
av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (%s)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic?ac->func_descr_generic:ac->func_descr)
int in_chunk_size
size of the chunks incoming RTMP packets are divided into
#define RTMP_CHANNELS
maximum possible number of different RTMP channels
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
RTMPPacketType type
packet payload type
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
channel for sending a/v to server
#define LIBAVFORMAT_IDENT
int flv_nb_packets
number of flv packets published
static const char signature[]
struct AVMD5 * av_md5_alloc(void)
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 av_always_inline double av_int2double(uint64_t i)
Reinterpret a 64-bit integer as a double.
#define RTMP_DEFAULT_PORT
uint32_t extra
probably an additional channel ID used during streaming data
ClientState state
current state
static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
Generate 'FCUnpublish' call and send it to the server.
#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)
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
int flv_size
current buffer size
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)
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
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
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 handle_client_bw(URLContext *s, RTMPPacket *pkt)
void av_md5_update(AVMD5 *ctx, const uint8_t *src, const int len)
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
char * pageurl
url of the web page
static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
char * flashver
version of the flash plugin
static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
ClientState
RTMP protocol handler state.
char * swfurl
url of the swf player
int main_channel_id
an additional channel ID which is used for some invocations
#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)
void av_log(void *avcl, int level, const char *fmt,...)
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)
client has not done anything yet
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
#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...
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
RTMPPacket prev_pkt[2][RTMP_CHANNELS]
packet history used when reading and sending packets
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.
client has started sending multimedia data to server (for output)
#define AVIO_FLAG_NONBLOCK
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.
client has started receiving multimedia data from server
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
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 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
static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
int flv_off
number of bytes read from current buffer
int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, int chunk_size, RTMPPacket *prev_pkt)
Send RTMP packet to the server.
#define AVIO_FLAG_READ_WRITE
char * av_strdup(const char *s)
Duplicate the string s.
static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
uint32_t bytes_read
number of bytes read from server
struct AVSHA * av_sha_alloc(void)
Allocate an AVSHA context.
void av_md5_init(AVMD5 *ctx)
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
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.
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 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)
uint8_t flv_header[11]
partial incoming flv packet header
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)
int listen
listen mode flag
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)
int ffurl_close(URLContext *h)
Close the resource accessed by the URLContext h, and free the memory used by it.
#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.
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.
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 ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
#define AVERROR_INVALIDDATA
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
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)
int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket *prev_pkt, uint8_t hdr)
Read internal RTMP packet sent by the server.
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)
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
struct TrackedMethod TrackedMethod
int swfsize
size of the decompressed SWF file
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.
unbuffered private I/O API
invoke some stream action
uint32_t av_get_random_seed(void)
Get random data.
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)
if(!(ptr_align%ac->ptr_align)&&samples_align >=aligned_len)