Go to the documentation of this file.
27 #include "config_components.h"
54 #define APP_MAX_LENGTH 1024
55 #define TCURL_MAX_LENGTH 1024
56 #define FLASHVER_MAX_LENGTH 64
57 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
58 #define RTMP_HEADER 11
139 #define PLAYER_KEY_OPEN_PART_LEN 30
142 'G',
'e',
'n',
'u',
'i',
'n',
'e',
' ',
'A',
'd',
'o',
'b',
'e',
' ',
143 'F',
'l',
'a',
's',
'h',
' ',
'P',
'l',
'a',
'y',
'e',
'r',
' ',
'0',
'0',
'1',
145 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
146 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
147 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
150 #define SERVER_KEY_OPEN_PART_LEN 36
153 'G',
'e',
'n',
'u',
'i',
'n',
'e',
' ',
'A',
'd',
'o',
'b',
'e',
' ',
154 'F',
'l',
'a',
's',
'h',
' ',
'M',
'e',
'd',
'i',
'a',
' ',
155 'S',
'e',
'r',
'v',
'e',
'r',
' ',
'0',
'0',
'1',
157 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
158 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
159 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
197 char **tracked_method)
272 if (param[0] && param[1] ==
':') {
275 }
else if (param[0] ==
'N' && param[1] && param[2] ==
':') {
342 uint32_t list_len = 0;
344 int fourcc_str_len = strlen(fourcc_data);
347 if ((fourcc_str_len + 1) % 5 != 0) {
349 "should be of the form hvc1[,av01][,vp09][,...]\n");
353 list_len = (fourcc_str_len + 1) / 5;
359 if (!strncmp(fourcc_data,
"hvc1", 4) ||
360 !strncmp(fourcc_data,
"av01", 4) ||
361 !strncmp(fourcc_data,
"vp09", 4)) {
414 char *param = rt->
conn;
419 param += strspn(param,
" ");
422 sep = strchr(param,
' ');
444 #define RTMP_CTRL_ABORT_MESSAGE (2)
503 if (strcmp(
command,
"connect")) {
514 "app", tmpstr,
sizeof(tmpstr));
517 if (!
ret && strcmp(tmpstr, rt->
app))
544 bytestream_put_byte(&p, 2);
558 bytestream_put_be16(&p, 0);
559 bytestream_put_be32(&p, 0);
790 bytestream_put_be16(&p, 3);
911 if (ppkt->
size < 6) {
922 bytestream_put_be16(&p, 7);
943 bytestream_put_be16(&p, 27);
1009 const char *subscribe)
1016 0, 27 + strlen(subscribe))) < 0)
1038 int ret, digest_pos;
1064 int ret, digest_pos;
1074 if (!memcmp(digest, buf + digest_pos, 32))
1087 "Hash of the decompressed SWF file is not 32 bytes long.\n");
1092 bytestream_put_byte(&p, 1);
1093 bytestream_put_byte(&p, 1);
1094 bytestream_put_be32(&p, rt->
swfsize);
1095 bytestream_put_be32(&p, rt->
swfsize);
1104 static int rtmp_uncompress_swfplayer(uint8_t *in_data,
int64_t in_size,
1107 z_stream zs = { 0 };
1112 zs.avail_in = in_size;
1113 zs.next_in = in_data;
1114 ret = inflateInit(&zs);
1119 uint8_t tmp_buf[16384];
1121 zs.avail_out =
sizeof(tmp_buf);
1122 zs.next_out = tmp_buf;
1125 if (
ret != Z_OK &&
ret != Z_STREAM_END) {
1130 size =
sizeof(tmp_buf) - zs.avail_out;
1139 }
while (zs.avail_out == 0);
1150 uint8_t *in_data =
NULL, *out_data =
NULL, *swfdata;
1159 &
s->interrupt_callback,
NULL,
1160 s->protocol_whitelist,
s->protocol_blacklist,
s)) < 0) {
1183 if (!memcmp(in_data,
"CWS", 3)) {
1192 memcpy(out_data, in_data, 8);
1195 if ((
ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1202 "Zlib is required for decompressing the SWF player file.\n");
1213 "Genuine Adobe Flash Player 001", 30,
1248 int server_pos, client_pos;
1259 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
1299 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1301 if (rt->
is_input && serverdata[5] >= 3) {
1337 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
1341 tosend + 1,
type)) < 0)
1367 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
1379 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
1385 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
1389 tosend + 1, 1)) < 0)
1392 if (serverdata[0] == 9) {
1403 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->
encrypted) {
1414 uint32_t *second_int,
char *arraydata,
1425 " not following standard\n", (
int)inoutsize);
1429 *first_int =
AV_RB32(arraydata);
1430 *second_int =
AV_RB32(arraydata + 4);
1435 uint32_t second_int,
char *arraydata,
int size)
1439 AV_WB32(arraydata, first_int);
1440 AV_WB32(arraydata + 4, second_int);
1458 uint32_t hs_my_epoch;
1468 if (inoutsize <= 0) {
1479 "Unable to write answer - RTMP S0\n");
1491 hs_my_epoch = hs_epoch;
1517 if (
temp != hs_my_epoch)
1519 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1520 if (memcmp(
buffer + 8, hs_s1 + 8,
1523 "Erroneous C2 Message random does not match up\n");
1535 "Too short chunk size change packet (%d)\n",
1576 }
else if (t == 26) {
1594 "Peer bandwidth packet is less than 4 bytes long (%d)\n",
1621 "Too short window acknowledgement size packet (%d)\n",
1642 const char *opaque,
const char *challenge)
1670 "?authmod=%s&user=%s&challenge=%s&response=%s",
1671 "adobe", user, challenge2, hashstr);
1674 "&opaque=%s", opaque);
1683 char hashstr1[33], hashstr2[33];
1684 const char *realm =
"live";
1685 const char *method =
"publish";
1686 const char *qop =
"auth";
1687 const char *nc =
"00000001";
1708 if (!strchr(rt->
app,
'/'))
1730 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1731 "llnw", user, nonce, cnonce, nc, hashstr1);
1740 char buf[300], *ptr, authmod[15];
1742 const char *user =
"", *salt =
"", *opaque =
NULL,
1745 if (!(cptr = strstr(
desc,
"authmod=adobe")) &&
1746 !(cptr = strstr(
desc,
"authmod=llnw"))) {
1748 "Unknown connect error (unsupported authentication method?)\n");
1751 cptr += strlen(
"authmod=");
1752 while (*cptr && *cptr !=
' ' &&
i <
sizeof(authmod) - 1)
1753 authmod[
i++] = *cptr++;
1761 if (strstr(
desc,
"?reason=authfailed")) {
1764 }
else if (strstr(
desc,
"?reason=nosuchuser")) {
1776 if (strstr(
desc,
"code=403 need auth")) {
1778 "?authmod=%s&user=%s", authmod, rt->
username);
1782 if (!(cptr = strstr(
desc,
"?reason=needauth"))) {
1791 char *next = strchr(ptr,
'&');
1792 char *
value = strchr(ptr,
'=');
1797 if (!strcmp(ptr,
"user")) {
1799 }
else if (!strcmp(ptr,
"salt")) {
1801 }
else if (!strcmp(ptr,
"opaque")) {
1803 }
else if (!strcmp(ptr,
"challenge")) {
1805 }
else if (!strcmp(ptr,
"nonce")) {
1816 if (!strcmp(authmod,
"adobe")) {
1832 char *tracked_method =
NULL;
1834 uint8_t tmpstr[256];
1841 "description", tmpstr,
sizeof(tmpstr))) {
1842 if (tracked_method && (!strcmp(tracked_method,
"_checkbw") ||
1843 !strcmp(tracked_method,
"releaseStream") ||
1844 !strcmp(tracked_method,
"FCSubscribe") ||
1845 !strcmp(tracked_method,
"FCPublish"))) {
1849 }
else if (tracked_method && !strcmp(tracked_method,
"getStreamLength")) {
1852 }
else if (tracked_method && !strcmp(tracked_method,
"connect")) {
1882 bytestream2_put_be16(&pbc, 0);
1962 if (!strcmp(
command,
"FCPublish") ||
1963 !strcmp(
command,
"publish")) {
1965 sizeof(filename), &stringlen);
1975 pchar = strrchr(
s->filename,
'/');
1978 "Unable to find / in url %s, bad format\n",
1980 pchar =
s->filename;
1983 if (strcmp(pchar, filename))
1985 " %s\n", filename, pchar);
1990 if (!strcmp(
command,
"FCPublish")) {
1999 }
else if (!strcmp(
command,
"publish")) {
2000 char statusmsg[128];
2001 snprintf(statusmsg,
sizeof(statusmsg),
"%s is now published", filename);
2008 statusmsg, filename);
2009 }
else if (!strcmp(
command,
"play")) {
2015 "playing stream",
NULL);
2027 if (!strcmp(
command,
"createStream")) {
2056 uint8_t strbuffer[8];
2066 if (strcmp(strbuffer,
"_result"))
2078 *number = numbuffer;
2086 char *tracked_method =
NULL;
2092 if (!tracked_method) {
2097 if (!strcmp(tracked_method,
"connect")) {
2118 }
else if (rt->
live == -1) {
2123 }
else if (!strcmp(tracked_method,
"createStream")) {
2135 if (rt->
live != -1) {
2144 }
else if (!strcmp(tracked_method,
"getStreamLength")) {
2160 uint8_t tmpstr[256];
2163 for (
i = 0;
i < 2;
i++) {
2171 if (!t && !strcmp(tmpstr,
"error")) {
2173 "description", tmpstr,
sizeof(tmpstr));
2174 if (t || !tmpstr[0])
2176 tmpstr,
sizeof(tmpstr));
2185 if (!t && !strcmp(tmpstr,
"NetStream.Play.UnpublishNotify")) rt->
state =
STATE_STOPPED;
2239 return old_flv_size;
2244 int old_flv_size,
ret;
2248 uint32_t ts =
pkt->timestamp;
2264 bytestream2_put_byte(&pbc,
pkt->type);
2265 bytestream2_put_be24(&pbc,
size);
2266 bytestream2_put_be24(&pbc, ts);
2267 bytestream2_put_byte(&pbc, ts >> 24);
2268 bytestream2_put_be24(&pbc, 0);
2278 uint8_t commandbuffer[64];
2279 char statusmsg[128];
2288 if (!strcmp(commandbuffer,
"onMetaData")) {
2308 if (!strcmp(statusmsg,
"videocodecid")) {
2311 if (!strcmp(statusmsg,
"audiocodecid")) {
2321 if (!strcmp(commandbuffer,
"@setDataFrame")) {
2324 sizeof(statusmsg), &stringlen);
2346 switch (
pkt->type) {
2386 const uint8_t *next;
2389 uint32_t ts, cts,
pts = 0;
2402 ts =
pkt->timestamp;
2405 type = bytestream_get_byte(&next);
2406 size = bytestream_get_be24(&next);
2407 cts = bytestream_get_be24(&next);
2408 cts |= bytestream_get_byte(&next) << 24;
2415 bytestream_put_byte(&p,
type);
2416 bytestream_put_be24(&p,
size);
2417 bytestream_put_be24(&p, ts);
2418 bytestream_put_byte(&p, ts >> 24);
2419 memcpy(p, next,
size + 3 + 4);
2422 next +=
size + 3 + 4;
2426 "RTMP_PT_METADATA packet\n");
2543 for (
i = 0;
i < 2;
i++) {
2573 uint8_t* old_flv_data = rt->
flv_data;
2581 memcpy(rt->
flv_data, old_flv_data, 13);
2591 bytestream_put_be24(&p, 40);
2592 bytestream_put_be24(&p, 0);
2593 bytestream_put_be32(&p, 0);
2598 bytestream_put_be16(&p, 10);
2603 bytestream_put_be32(&p, 1);
2606 bytestream_put_be16(&p, 8);
2612 bytestream_put_be16(&p, 0);
2631 char proto[8], hostname[256], path[1024], auth[100], *fname;
2632 char *old_app, *qmark, *n, fname_buffer[1024];
2643 hostname,
sizeof(hostname), &port,
2644 path,
sizeof(path),
s->filename);
2646 n = strchr(path,
' ');
2649 "Detected librtmp style URL parameters, these aren't supported "
2650 "by the libavformat internal RTMP handler currently enabled. "
2651 "See the documentation for the correct way to pass parameters.\n");
2656 char *ptr = strchr(auth,
':');
2664 if (rt->
listen && strcmp(proto,
"rtmp")) {
2669 if (!strcmp(proto,
"rtmpt") || !strcmp(proto,
"rtmpts")) {
2670 if (!strcmp(proto,
"rtmpts"))
2675 }
else if (!strcmp(proto,
"rtmps")) {
2680 }
else if (!strcmp(proto,
"rtmpe") || (!strcmp(proto,
"rtmpte"))) {
2681 if (!strcmp(proto,
"rtmpte"))
2693 "?listen&listen_timeout=%d&tcp_nodelay=%d",
2701 &
s->interrupt_callback,
opts,
2702 s->protocol_whitelist,
s->protocol_blacklist,
s)) < 0) {
2732 qmark = strchr(path,
'?');
2733 if (qmark && strstr(qmark,
"slist=")) {
2737 fname = strstr(path,
"slist=") + 6;
2739 amp = strchr(fname,
'&');
2742 sizeof(fname_buffer)));
2743 fname = fname_buffer;
2745 }
else if (!strncmp(path,
"/ondemand/", 10)) {
2747 memcpy(rt->
app,
"ondemand", 9);
2749 char *next = *path ? path + 1 : path;
2750 char *p = strchr(next,
'/');
2762 char *
c = strchr(p + 1,
':');
2763 fname = strchr(p + 1,
'/');
2764 if (!fname || (
c &&
c < fname)) {
2787 max_len = strlen(fname) + 5;
2795 int len = strlen(fname);
2796 if (!strchr(fname,
':') &&
len >= 4 &&
2797 (!strcmp(fname +
len - 4,
".f4v") ||
2798 !strcmp(fname +
len - 4,
".mp4"))) {
2801 if (
len >= 4 && !strcmp(fname +
len - 4,
".flv"))
2802 fname[
len - 4] =
'\0';
2818 port,
"/%s", rt->
app);
2867 for (
i = 0;
i < 2;
i++)
2932 int orig_size =
size;
2938 if (data_left >=
size) {
2943 if (data_left > 0) {
2963 "Seek on stream index %d at timestamp %"PRId64
" with flags %08x\n",
2964 stream_index, timestamp,
flags);
2967 "Unable to send seek command on stream index %d at timestamp "
2968 "%"PRId64
" with flags %08x\n",
2969 stream_index, timestamp,
flags);
2995 int size_temp =
size;
2996 int pktsize, pkttype,
copy;
2998 const uint8_t *buf_temp = buf;
3022 pkttype = bytestream_get_byte(&
header);
3023 pktsize = bytestream_get_be24(&
header);
3024 ts = bytestream_get_be24(&
header);
3025 ts |= bytestream_get_byte(&
header) << 24;
3026 bytestream_get_be24(&
header);
3046 pkttype, ts, pktsize)) < 0)
3066 uint8_t commandbuffer[64];
3073 if (!strcmp(commandbuffer,
"onMetaData") ||
3074 !strcmp(commandbuffer,
"|RtmpSampleAccess")) {
3095 }
while (buf_temp - buf <
size);
3113 }
else if (
ret < 0) {
3115 }
else if (
ret == 1) {
3133 #define OFFSET(x) offsetof(RTMPContext, x)
3134 #define DEC AV_OPT_FLAG_DECODING_PARAM
3135 #define ENC AV_OPT_FLAG_ENCODING_PARAM
3139 {
"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},
3142 {
"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},
3143 {
"rtmp_enhanced_codecs",
"Specify the codec(s) to use in an enhanced rtmp live stream",
OFFSET(enhanced_codecs),
AV_OPT_TYPE_STRING, {.str =
NULL }, 0, 0,
ENC},
3144 {
"rtmp_live",
"Specify that the media is a live stream.",
OFFSET(live),
AV_OPT_TYPE_INT, {.i64 = -2}, INT_MIN, INT_MAX,
DEC, .unit =
"rtmp_live"},
3147 {
"recorded",
"recorded stream", 0,
AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0,
DEC, .unit =
"rtmp_live"},
3148 {
"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},
3150 {
"rtmp_subscribe",
"Name of live stream to subscribe to. Defaults to rtmp_playpath.",
OFFSET(subscribe),
AV_OPT_TYPE_STRING, {.str =
NULL }, 0, 0,
DEC},
3152 {
"rtmp_swfsize",
"Size of the decompressed SWF file, required for SWFVerification.",
OFFSET(swfsize),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX,
DEC},
3156 {
"rtmp_listen",
"Listen for incoming rtmp connections",
OFFSET(listen),
AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX,
DEC, .unit =
"rtmp_listen" },
3157 {
"listen",
"Listen for incoming rtmp connections",
OFFSET(listen),
AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX,
DEC, .unit =
"rtmp_listen" },
3159 {
"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, .unit =
"rtmp_listen" },
3163 #define RTMP_PROTOCOL_0(flavor)
3164 #define RTMP_PROTOCOL_1(flavor) \
3165 static const AVClass flavor##_class = { \
3166 .class_name = #flavor, \
3167 .item_name = av_default_item_name, \
3168 .option = rtmp_options, \
3169 .version = LIBAVUTIL_VERSION_INT, \
3172 const URLProtocol ff_##flavor##_protocol = { \
3174 .url_open2 = rtmp_open, \
3175 .url_read = rtmp_read, \
3176 .url_read_seek = rtmp_seek, \
3177 .url_read_pause = rtmp_pause, \
3178 .url_write = rtmp_write, \
3179 .url_close = rtmp_close, \
3180 .priv_data_size = sizeof(RTMPContext), \
3181 .flags = URL_PROTOCOL_FLAG_NETWORK, \
3182 .priv_data_class= &flavor##_class, \
3184 #define RTMP_PROTOCOL_2(flavor, enabled) \
3185 RTMP_PROTOCOL_ ## enabled(flavor)
3186 #define RTMP_PROTOCOL_3(flavor, config) \
3187 RTMP_PROTOCOL_2(flavor, config)
3188 #define RTMP_PROTOCOL(flavor, uppercase) \
3189 RTMP_PROTOCOL_3(flavor, CONFIG_ ## uppercase ## _PROTOCOL)
@ RTMP_PT_METADATA
FLV metadata.
char * enhanced_codecs
codec list in enhanced rtmp
char * subscribe
name of live stream to subscribe
static 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.
static int rtmp_receive_hs_packet(RTMPContext *rt, uint32_t *first_int, uint32_t *second_int, char *arraydata, int size)
static int handle_window_ack_size(URLContext *s, RTMPPacket *pkt)
@ STATE_SEEKING
client has started the seek operation. Back on STATE_PLAYING when the time comes
#define AMF_END_OF_OBJECT
int ff_rtmpe_update_keystream(URLContext *h)
Update the keystream and set RC4 keys for encryption.
#define AV_LOG_WARNING
Something somehow does not look correct.
static int read_number_result(RTMPPacket *pkt, double *number)
Read the AMF_NUMBER response ("_result") to a function call (e.g.
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
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)
int in_chunk_size
size of the chunks incoming RTMP packets are divided into
uint64_t bytes_read
number of bytes read from server
#define RTMP_HANDSHAKE_PACKET_SIZE
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
int client_buffer_time
client buffer time in ms
int flv_header_bytes
number of initialized bytes in flv_header
@ RTMP_NETWORK_CHANNEL
channel for network-related messages (bandwidth report, ping, etc)
@ RTMP_PT_BYTES_READ
number of bytes read
char * app
name of application
static int gen_swf_verification(URLContext *s, RTMPContext *rt)
Generate SWF verification message and send it to the server.
static int rtmp_close(URLContext *h)
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
RTMPPacketType type
packet payload type
double strtod(const char *, char **)
#define AVERROR_EOF
End of file.
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
uint64_t last_bytes_read
number of bytes read last reported to server
static int write_begin(URLContext *s)
RTMPPacket out_pkt
rtmp packet, created from flv a/v or metadata (for output)
@ RTMP_PT_NOTIFY
some notification
static int gen_buffer_time(URLContext *s, RTMPContext *rt)
Generate client buffer time and send it to the server.
static int ffurl_write(URLContext *h, const uint8_t *buf, int size)
Write size bytes from buf to the resource accessed by h.
static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
Generate 'FCPublish' call and send it to the server.
char * pageurl
url of the web page
@ STATE_RECEIVING
received a publish command (for input)
static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
Parse received packet and possibly perform some action depending on the packet contents.
static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt, uint8_t *buf)
int max_packet_size
if non zero, the stream is packetized with this max packet size
#define AVSEEK_SIZE
ORing this as the "whence" parameter to a seek function causes it to return the filesize without seek...
void ff_amf_write_field_name(uint8_t **dst, const char *str)
Write string used as field name in AMF object to buffer.
int nb_tracked_methods
number of tracked methods
#define AV_LOG_VERBOSE
Detailed information.
int ff_amf_match_string(const uint8_t *data, int size, const char *str)
Match AMF string with a NULL-terminated string.
@ RTMP_PT_WINDOW_ACK_SIZE
window acknowledgement size
int ffurl_close(URLContext *h)
uint8_t * flv_data
buffer with data for demuxer
ClientState state
current state
static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
Generate ping reply and send it to the server.
@ STATE_PUBLISHING
client has started sending multimedia data to server (for output)
int listen_timeout
listen timeout to wait for new connections
@ STATE_FCPUBLISH
client FCPublishing stream (for output)
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
uint32_t extra
probably an additional channel ID used during streaming data
int max_sent_unacked
max unacked sent bytes
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 gen_pause(URLContext *s, RTMPContext *rt, int pause, uint32_t timestamp)
Generate a pause packet that either pauses or unpauses the current stream.
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
void ff_amf_write_bool(uint8_t **dst, int val)
Write boolean value in AMF format to buffer.
char * conn
append arbitrary AMF data to the Connect message
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
int live
0: recorded, -1: live, -2: both
static int write_status(URLContext *s, RTMPPacket *pkt, const char *status, const char *description, const char *details)
@ RTMP_VIDEO_CHANNEL
channel for video data
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
static int add_tracked_method(RTMPContext *rt, const char *name, int id)
@ AV_OPT_TYPE_BINARY
Underlying C type is a uint8_t* that is either NULL or points to an array allocated with the av_mallo...
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.
static int update_offset(RTMPContext *rt, int size)
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
int nb_invokes
keeps track of invoke messages
int stream_id
ID assigned by the server for the stream.
static int gen_release_stream(URLContext *s, RTMPContext *rt)
Generate 'releaseStream' call and send it to the server.
int skip_bytes
number of bytes to skip from the input FLV stream in the next write call
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
int nb_prev_pkt[2]
number of elements in prev_pkt
int ff_amf_get_string(GetByteContext *bc, uint8_t *str, int strsize, int *length)
Get AMF string value.
static int gen_publish(URLContext *s, RTMPContext *rt)
Generate 'publish' call and send it to the server.
static int rtmp_pause(void *opaque, int pause)
static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
static void free_tracked_methods(RTMPContext *rt)
static const char signature[]
static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
Generate 'FCUnpublish' call and send it to the server.
int flv_off
number of bytes read from current buffer
static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset, char **tracked_method)
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
void ff_amf_write_string(uint8_t **dst, const char *str)
Write string in AMF format to buffer.
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
static int handle_notify(URLContext *s, RTMPPacket *pkt)
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it.
static int rtmp_send_hs_packet(RTMPContext *rt, uint32_t first_int, uint32_t second_int, char *arraydata, int size)
#define RTMPS_DEFAULT_PORT
@ RTMP_SYSTEM_CHANNEL
channel for sending server control messages
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
char * swfhash
SHA256 hash of the decompressed SWF file (32 bytes)
static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, const uint8_t *src, unsigned int size)
char * flashver
version of the flash plugin
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
#define AVIO_FLAG_WRITE
write-only
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
int listen
listen mode flag
static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt, const char *opaque, const char *challenge)
#define RTMP_CLIENT_PLATFORM
emulated Flash client version - 9.0.124.2 on Linux
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this field
int has_video
presence of video data
static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
static const uint8_t rtmp_server_key[]
Key used for RTMP server digest signing.
uint32_t receive_report_size
number of bytes after which we should report the number of received bytes to the peer
#define RTMP_PKTDATA_DEFAULT_SIZE
static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
#define RTMP_CTRL_ABORT_MESSAGE
int received_metadata
Indicates if we have received metadata about the streams.
Describe the class of an AVClass context structure.
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.
int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags)
static int gen_connect(URLContext *s, RTMPContext *rt)
Generate 'connect' call and send it to the server.
structure for holding RTMP packets
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
int ff_rtmpe_gen_pub_key(URLContext *h, uint8_t *buf)
Initialize the Diffie-Hellmann context and generate the public key.
void ff_amf_write_object_end(uint8_t **dst)
Write marker for end of AMF object to buffer.
static int64_t rtmp_seek(void *opaque, int stream_index, int64_t timestamp, int flags)
void ff_rtmp_packet_destroy(RTMPPacket *pkt)
Free RTMP packet.
char * swfurl
url of the swf player
int tcp_nodelay
Use TCP_NODELAY to disable Nagle's algorithm if set to 1.
static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
@ RTMP_PT_USER_CONTROL
user control
static const uint8_t rtmp_player_key[]
Client key used for digest signing.
static int gen_delete_stream(URLContext *s, RTMPContext *rt)
Generate 'deleteStream' call and send it to the server.
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.
char * tcurl
url of the target stream
int size
packet payload size
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...
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
static int handle_user_control(URLContext *s, RTMPPacket *pkt)
static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
int swfhash_len
length of the SHA256 hash
#define RTMP_DEFAULT_PORT
static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
Context structure for the Lagged Fibonacci PRNG.
#define FLASHVER_MAX_LENGTH
static int gen_create_stream(URLContext *s, RTMPContext *rt)
Generate 'createStream' call and send it to the server.
static void copy(const float *p1, float *p2, const int length)
static int read_connect(URLContext *s, RTMPContext *rt)
#define RTMP_PROTOCOL(flavor, uppercase)
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.
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
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.
int out_chunk_size
size of the chunks outgoing RTMP packets are divided into
@ RTMP_PT_INVOKE
invoke some stream action
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
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
TrackedMethod * tracked_methods
tracked methods buffer
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.
static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **opts)
Open RTMP connection and verify that the stream can be played.
#define SERVER_KEY_OPEN_PART_LEN
length of partial key used for first server digest signing
static const AVOption rtmp_options[]
static const uint8_t header[24]
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate an array through a pointer to a pointer.
void ff_amf_write_null(uint8_t **dst)
Write AMF NULL value to buffer.
int flv_nb_packets
number of flv packets published
void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
Print information and contents of RTMP packet.
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
char * swfverify
URL to player swf file, compute hash/size automatically.
@ FLV_HEADER_FLAG_HASVIDEO
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
int swfsize
size of the decompressed SWF file
int tracked_methods_size
size of the tracked methods buffer
int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type, int timestamp, int size)
Create new RTMP packet with given attributes.
#define AV_LOG_INFO
Standard information.
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.
static av_always_inline uint64_t av_double2int(double f)
Reinterpret a double as a 64-bit integer.
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
void av_md5_init(AVMD5 *ctx)
Initialize MD5 hashing.
#define AV_BASE64_SIZE(x)
Calculate the output size needed to base64-encode x bytes to a null-terminated string.
static int rtmp_validate_digest(uint8_t *buf, int off)
Verify that the received server response has the expected digest value.
#define i(width, name, range_min, range_max)
static int rtmp_calc_swfhash(URLContext *s)
static int gen_check_bw(URLContext *s, RTMPContext *rt)
Generate check bandwidth message and send it to the server.
static int handle_connect_error(URLContext *s, const char *desc)
static av_always_inline void bytestream2_skip_p(PutByteContext *p, unsigned int size)
int flush_interval
number of packets flushed in the same request (RTMPT only)
uint32_t timestamp
packet full timestamp
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.
char * playpath
stream identifier to play (with possible "mp4:" prefix)
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default 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 void del_tracked_method(RTMPContext *rt, int index)
static int handle_set_peer_bw(URLContext *s, RTMPPacket *pkt)
const uint8_t * buffer_end
void av_md5_final(AVMD5 *ctx, uint8_t *dst)
Finish hashing and output digest value.
#define PLAYER_KEY_OPEN_PART_LEN
length of partial key used for first client digest signing
@ FLV_HEADER_FLAG_HASAUDIO
@ RTMP_PT_SET_PEER_BW
peer bandwidth
@ AMF_DATA_TYPE_MIXEDARRAY
static int handle_invoke(URLContext *s, RTMPPacket *pkt)
static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, uint8_t *dst, unsigned int size)
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.
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
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)
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,...
int nb_streamid
The next stream id to return on createStream calls.
int encrypted
use an encrypted connection (RTMPE only)
int ff_amf_read_number(GetByteContext *bc, double *val)
Read AMF number value.
#define AV_DICT_MATCH_CASE
Only get an entry with exact-case key match.
@ STATE_SENDING
received a play command (for output)
void ff_amf_write_number(uint8_t **dst, double val)
Write number in AMF format to buffer.
int channel_id
RTMP channel ID (nothing to do with audio/video channels though)
void ff_amf_write_array_start(uint8_t **dst, uint32_t length)
Write marker and length for AMF array to buffer.
static int gen_window_ack_size(URLContext *s, RTMPContext *rt)
Generate window acknowledgement size message and send it to the server.
void ff_rtmpe_encrypt_sig(URLContext *h, uint8_t *sig, const uint8_t *digest, int type)
Encrypt the signature.
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.
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
ClientState
RTMP protocol handler state.
uint8_t * data
packet payload
struct AVMD5 * av_md5_alloc(void)
Allocate an AVMD5 context.
@ AV_OPT_TYPE_INT
Underlying C type is int.
void ff_amf_write_object_start(uint8_t **dst)
Write marker for AMF object to buffer.
int is_input
input/output flag
static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt, const char *subscribe)
char * av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
Encode data to base64 and null-terminate.
void av_md5_update(AVMD5 *ctx, const uint8_t *src, size_t len)
Update hash value.
double duration
Duration of the stream in seconds as returned by the server (only valid if non-zero)
char swfverification[42]
hash of the SWF verification
uint8_t flv_header[RTMP_HEADER]
partial incoming flv packet header
uint32_t last_timestamp
last timestamp received in a packet
#define AVIO_FLAG_READ
read-only
char * av_strdup(const char *s)
Duplicate a string.
URLContext * stream
TCP stream used in interactions with RTMP server.
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.
@ STATE_PLAYING
client has started receiving multimedia data from server
@ STATE_START
client has not done anything yet
static int gen_get_stream_length(URLContext *s, RTMPContext *rt)
Generate 'getStreamLength' call and send it to the server.
static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
static int rtmp_handshake(URLContext *s, RTMPContext *rt)
Perform handshake with the server by means of exchanging pseudorandom data signed with HMAC-SHA2 dige...
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
#define flags(name, subs,...)
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.
@ STATE_STOPPED
the broadcast has been stopped
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
@ STATE_HANDSHAKED
client has performed handshake
static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
rtmp handshake server side
int flv_size
current buffer size
@ RTMP_AUDIO_CHANNEL
channel for audio data
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
@ RTMP_PT_AUDIO
audio packet
static int rtmp_read(URLContext *s, uint8_t *buf, int size)
int ff_amf_read_null(GetByteContext *bc)
Read AMF NULL value.
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...
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ RTMP_PT_VIDEO
video packet
@ RTMP_SOURCE_CHANNEL
channel for a/v invokes
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
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.
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
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
static int ffurl_read(URLContext *h, uint8_t *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.
@ RTMP_PT_CHUNK_SIZE
chunk size change
int ff_amf_read_string(GetByteContext *bc, uint8_t *str, int strsize, int *length)
Read AMF string value.