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
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
204 char **tracked_method)
279 if (param[0] && param[1] ==
':') {
282 }
else if (param[0] ==
'N' && param[1] && param[2] ==
':') {
285 value = strchr(field,
':');
358 uint32_t list_len = 0;
360 int fourcc_str_len = strlen(fourcc_data);
363 if ((fourcc_str_len + 1) % 5 != 0) {
365 "should be of the form hvc1[,av01][,vp09][,vvc1][,...]\n");
370 list_len = (fourcc_str_len + 1) / 5;
376 if (!strncmp(fourcc_data,
"ac-3", 4) ||
377 !strncmp(fourcc_data,
"av01", 4) ||
378 !strncmp(fourcc_data,
"avc1", 4) ||
379 !strncmp(fourcc_data,
"ec-3", 4) ||
380 !strncmp(fourcc_data,
"fLaC", 4) ||
381 !strncmp(fourcc_data,
"hvc1", 4) ||
382 !strncmp(fourcc_data,
"vvc1", 4) ||
383 !strncmp(fourcc_data,
".mp3", 4) ||
384 !strncmp(fourcc_data,
"mp4a", 4) ||
385 !strncmp(fourcc_data,
"Opus", 4) ||
386 !strncmp(fourcc_data,
"vp09", 4)) {
440 char *param = rt->
conn;
445 param += strspn(param,
" ");
448 sep = strchr(param,
' ');
470#define RTMP_CTRL_ABORT_MESSAGE (2)
529 if (strcmp(
command,
"connect")) {
540 "app", tmpstr,
sizeof(tmpstr));
543 if (!ret && strcmp(tmpstr, rt->
app))
570 bytestream_put_byte(&p, 2);
584 bytestream_put_be16(&p, 0);
585 bytestream_put_be32(&p, 0);
816 bytestream_put_be16(&p, 3);
937 if (ppkt->
size < 6) {
948 bytestream_put_be16(&p, 7);
969 bytestream_put_be16(&p, 27);
1035 const char *subscribe)
1042 0, 27 + strlen(subscribe))) < 0)
1064 int ret, digest_pos;
1090 int ret, digest_pos;
1100 if (!memcmp(digest, buf + digest_pos, 32))
1113 "Hash of the decompressed SWF file is not 32 bytes long.\n");
1118 bytestream_put_byte(&p, 1);
1119 bytestream_put_byte(&p, 1);
1120 bytestream_put_be32(&p, rt->
swfsize);
1121 bytestream_put_be32(&p, rt->
swfsize);
1130static int rtmp_uncompress_swfplayer(uint8_t *in_data,
int64_t in_size,
1133 z_stream zs = { 0 };
1138 zs.avail_in = in_size;
1139 zs.next_in = in_data;
1140 ret = inflateInit(&zs);
1145 uint8_t tmp_buf[16384];
1147 zs.avail_out =
sizeof(tmp_buf);
1148 zs.next_out = tmp_buf;
1150 ret =
inflate(&zs, Z_NO_FLUSH);
1151 if (ret != Z_OK && ret != Z_STREAM_END) {
1156 size =
sizeof(tmp_buf) - zs.avail_out;
1165 }
while (zs.avail_out == 0);
1176 uint8_t *in_data =
NULL, *out_data =
NULL, *swfdata;
1185 &
s->interrupt_callback,
NULL,
1186 s->protocol_whitelist,
s->protocol_blacklist,
s)) < 0) {
1209 if (!memcmp(in_data,
"CWS", 3)) {
1222 memcpy(out_data, in_data, 8);
1225 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1232 "Zlib is required for decompressing the SWF player file.\n");
1243 "Genuine Adobe Flash Player 001", 30,
1278 int server_pos, client_pos;
1281#if CONFIG_FFRTMPCRYPT_PROTOCOL
1292#if CONFIG_FFRTMPCRYPT_PROTOCOL
1334 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1336 if (rt->
is_input && serverdata[5] >= 3) {
1342#if CONFIG_FFRTMPCRYPT_PROTOCOL
1374#if CONFIG_FFRTMPCRYPT_PROTOCOL
1379 tosend + 1,
type)) < 0)
1406#if CONFIG_FFRTMPCRYPT_PROTOCOL
1420#if CONFIG_FFRTMPCRYPT_PROTOCOL
1428#if CONFIG_FFRTMPCRYPT_PROTOCOL
1433 tosend + 1, 1)) < 0)
1436 if (serverdata[0] == 9) {
1448#if CONFIG_FFRTMPCRYPT_PROTOCOL
1461 uint32_t *second_int,
char *arraydata,
1472 " not following standard\n", (
int)inoutsize);
1476 *first_int =
AV_RB32(arraydata);
1477 *second_int =
AV_RB32(arraydata + 4);
1482 uint32_t second_int,
char *arraydata,
int size)
1486 AV_WB32(arraydata, first_int);
1487 AV_WB32(arraydata + 4, second_int);
1505 uint32_t hs_my_epoch;
1515 if (inoutsize <= 0) {
1526 "Unable to write answer - RTMP S0\n");
1538 hs_my_epoch = hs_epoch;
1564 if (
temp != hs_my_epoch)
1566 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1567 if (memcmp(
buffer + 8, hs_s1 + 8,
1570 "Erroneous C2 Message random does not match up\n");
1580 if (
pkt->size < 4) {
1582 "Too short chunk size change packet (%d)\n",
1613 if (
pkt->size < 2) {
1623 }
else if (t == 26) {
1639 if (
pkt->size < 4) {
1641 "Peer bandwidth packet is less than 4 bytes long (%d)\n",
1666 if (
pkt->size < 4) {
1668 "Too short window acknowledgement size packet (%d)\n",
1689 const char *opaque,
const char *challenge)
1717 "?authmod=%s&user=%s&challenge=%s&response=%s",
1718 "adobe", user, challenge2, hashstr);
1721 "&opaque=%s", opaque);
1730 char hashstr1[33], hashstr2[33];
1731 const char *realm =
"live";
1732 const char *method =
"publish";
1733 const char *qop =
"auth";
1734 const char *nc =
"00000001";
1755 if (!strchr(rt->
app,
'/'))
1777 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1778 "llnw", user, nonce, cnonce, nc, hashstr1);
1787 char buf[300], *ptr, authmod[15];
1789 const char *user =
"", *salt =
"", *opaque =
NULL,
1792 if (!(cptr = strstr(
desc,
"authmod=adobe")) &&
1793 !(cptr = strstr(
desc,
"authmod=llnw"))) {
1795 "Unknown connect error (unsupported authentication method?)\n");
1798 cptr += strlen(
"authmod=");
1799 while (*cptr && *cptr !=
' ' &&
i <
sizeof(authmod) - 1)
1800 authmod[
i++] = *cptr++;
1808 if (strstr(
desc,
"?reason=authfailed")) {
1811 }
else if (strstr(
desc,
"?reason=nosuchuser")) {
1823 if (strstr(
desc,
"code=403 need auth")) {
1825 "?authmod=%s&user=%s", authmod, rt->
username);
1829 if (!(cptr = strstr(
desc,
"?reason=needauth"))) {
1838 char *next = strchr(ptr,
'&');
1839 char *
value = strchr(ptr,
'=');
1844 if (!strcmp(ptr,
"user")) {
1846 }
else if (!strcmp(ptr,
"salt")) {
1848 }
else if (!strcmp(ptr,
"opaque")) {
1850 }
else if (!strcmp(ptr,
"challenge")) {
1852 }
else if (!strcmp(ptr,
"nonce")) {
1863 if (!strcmp(authmod,
"adobe")) {
1864 if ((ret =
do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1878 const uint8_t *data_end =
pkt->data +
pkt->size;
1879 char *tracked_method =
NULL;
1881 uint8_t tmpstr[256];
1888 "description", tmpstr,
sizeof(tmpstr))) {
1889 if (tracked_method && (!strcmp(tracked_method,
"_checkbw") ||
1890 !strcmp(tracked_method,
"releaseStream") ||
1891 !strcmp(tracked_method,
"FCSubscribe") ||
1892 !strcmp(tracked_method,
"FCPublish"))) {
1896 }
else if (tracked_method && !strcmp(tracked_method,
"getStreamLength")) {
1899 }
else if (tracked_method && !strcmp(tracked_method,
"connect")) {
1929 bytestream2_put_be16(&pbc, 0);
1941 const char *status,
const char *description,
const char *details)
1951 + strlen(status) + strlen(description)
1992 const uint8_t *p =
pkt->data;
2011 if (!strcmp(
command,
"FCPublish") ||
2012 !strcmp(
command,
"publish")) {
2014 sizeof(filename), &stringlen);
2024 pchar = strrchr(
s->filename,
'/');
2027 "Unable to find / in url %s, bad format\n",
2029 pchar =
s->filename;
2032 if (strcmp(pchar, filename))
2034 " %s\n", filename, pchar);
2039 if (!strcmp(
command,
"FCPublish")) {
2048 }
else if (!strcmp(
command,
"publish")) {
2049 char statusmsg[
sizeof(filename) + 32];
2050 snprintf(statusmsg,
sizeof(statusmsg),
"%s is now published", filename);
2057 statusmsg, filename);
2058 }
else if (!strcmp(
command,
"play")) {
2064 "playing stream",
NULL);
2076 if (!strcmp(
command,
"createStream")) {
2105 uint8_t strbuffer[8];
2115 if (strcmp(strbuffer,
"_result"))
2127 *number = numbuffer;
2135 char *tracked_method =
NULL;
2141 if (!tracked_method) {
2146 if (!strcmp(tracked_method,
"connect")) {
2167 }
else if (rt->
live == -1) {
2172 }
else if (!strcmp(tracked_method,
"createStream")) {
2184 if (rt->
live != -1) {
2193 }
else if (!strcmp(tracked_method,
"getStreamLength")) {
2207 const uint8_t *data_end =
pkt->data +
pkt->size;
2209 uint8_t tmpstr[256];
2212 for (
i = 0;
i < 2;
i++) {
2220 if (!t && !strcmp(tmpstr,
"error")) {
2222 "description", tmpstr,
sizeof(tmpstr));
2223 if (t || !tmpstr[0])
2225 tmpstr,
sizeof(tmpstr));
2234 if (!t && !strcmp(tmpstr,
"NetStream.Play.UnpublishNotify")) rt->
state =
STATE_STOPPED;
2293 return old_flv_size;
2298 int old_flv_size, ret;
2302 uint32_t ts =
pkt->timestamp;
2310 if (
size > INT_MAX - 15)
2313 if (old_flv_size < 0)
2314 return old_flv_size;
2322 bytestream2_put_byte(&pbc,
pkt->type);
2323 bytestream2_put_be24(&pbc,
size);
2324 bytestream2_put_be24(&pbc, ts);
2325 bytestream2_put_byte(&pbc, ts >> 24);
2326 bytestream2_put_be24(&pbc, 0);
2336 uint8_t commandbuffer[64];
2337 char statusmsg[128];
2338 int stringlen, ret,
skip = 0;
2346 if (!strcmp(commandbuffer,
"onMetaData")) {
2366 if (!strcmp(statusmsg,
"videocodecid")) {
2369 if (!strcmp(statusmsg,
"audiocodecid")) {
2379 if (!strcmp(commandbuffer,
"@setDataFrame")) {
2382 sizeof(statusmsg), &stringlen);
2404 switch (
pkt->type) {
2443 int ret, old_flv_size,
type;
2447 uint32_t ts, cts,
pts = 0;
2450 if (old_flv_size < 0)
2451 return old_flv_size;
2463 ts =
pkt->timestamp;
2466 type = bytestream2_get_byte(&gbc);
2467 size = bytestream2_get_be24(&gbc);
2468 cts = bytestream2_get_be24(&gbc);
2469 cts |= bytestream2_get_byte(&gbc) << 24;
2476 bytestream2_put_byte(&pbc,
type);
2477 bytestream2_put_be24(&pbc,
size);
2478 bytestream2_put_be24(&pbc, ts);
2479 bytestream2_put_byte(&pbc, ts >> 24);
2486 "RTMP_PT_METADATA packet\n");
2603 for (
i = 0;
i < 2;
i++) {
2633 uint8_t* old_flv_data = rt->
flv_data;
2641 memcpy(rt->
flv_data, old_flv_data, 13);
2651 bytestream_put_be24(&p, 40);
2652 bytestream_put_be24(&p, 0);
2653 bytestream_put_be32(&p, 0);
2658 bytestream_put_be16(&p, 10);
2663 bytestream_put_be32(&p, 1);
2666 bytestream_put_be16(&p, 8);
2672 bytestream_put_be16(&p, 0);
2691 char proto[8], hostname[256], path[1024], auth[100], *fname;
2692 char *old_app, *qmark, *n, fname_buffer[1024];
2703 hostname,
sizeof(hostname), &port,
2704 path,
sizeof(path),
s->filename);
2706 n = strchr(path,
' ');
2709 "Detected librtmp style URL parameters, these aren't supported "
2710 "by the libavformat internal RTMP handler currently enabled. "
2711 "See the documentation for the correct way to pass parameters.\n");
2716 char *ptr = strchr(auth,
':');
2724 if (rt->
listen && strcmp(proto,
"rtmp")) {
2729 if (!strcmp(proto,
"rtmpt") || !strcmp(proto,
"rtmpts")) {
2730 if (!strcmp(proto,
"rtmpts"))
2735 }
else if (!strcmp(proto,
"rtmps")) {
2740 }
else if (!strcmp(proto,
"rtmpe") || (!strcmp(proto,
"rtmpte"))) {
2741 if (!strcmp(proto,
"rtmpte"))
2753 "?listen&listen_timeout=%d&tcp_nodelay=%d",
2762 &
s->interrupt_callback,
opts,
2763 s->protocol_whitelist,
s->protocol_blacklist,
s)) < 0) {
2793 qmark = strchr(path,
'?');
2794 if (qmark && strstr(qmark,
"slist=")) {
2798 fname = strstr(path,
"slist=") + 6;
2800 amp = strchr(fname,
'&');
2803 sizeof(fname_buffer)));
2804 fname = fname_buffer;
2806 }
else if (!strncmp(path,
"/ondemand/", 10)) {
2808 memcpy(rt->
app,
"ondemand", 9);
2810 char *next = *path ? path + 1 : path;
2811 char *p = strchr(next,
'/');
2823 char *
c = strchr(p + 1,
':');
2824 fname = strchr(p + 1,
'/');
2825 if (!fname || (
c &&
c < fname)) {
2848 max_len = strlen(fname) + 5;
2856 int len = strlen(fname);
2857 if (!strchr(fname,
':') &&
len >= 4 &&
2858 (!strcmp(fname +
len - 4,
".f4v") ||
2859 !strcmp(fname +
len - 4,
".mp4"))) {
2862 if (
len >= 4 && !strcmp(fname +
len - 4,
".flv"))
2863 fname[
len - 4] =
'\0';
2879 port,
"/%s", rt->
app);
2925 }
while (ret ==
AVERROR(EAGAIN));
2934 for (
i = 0;
i < 2;
i++)
2995 int orig_size =
size;
3001 if (data_left >=
size) {
3006 if (data_left > 0) {
3026 "Seek on stream index %d at timestamp %"PRId64
" with flags %08x\n",
3027 stream_index, timestamp,
flags);
3028 if ((ret =
gen_seek(
s, rt, timestamp)) < 0) {
3030 "Unable to send seek command on stream index %d at timestamp "
3031 "%"PRId64
" with flags %08x\n",
3032 stream_index, timestamp,
flags);
3058 int size_temp =
size;
3059 int pktsize, pkttype,
copy;
3061 const uint8_t *buf_temp = buf;
3085 pkttype = bytestream_get_byte(&
header);
3086 pktsize = bytestream_get_be24(&
header);
3087 ts = bytestream_get_be24(&
header);
3088 ts |= bytestream_get_byte(&
header) << 24;
3089 bytestream_get_be24(&
header);
3109 pkttype, ts, pktsize)) < 0)
3134 uint8_t commandbuffer[64];
3141 if (!strcmp(commandbuffer,
"onMetaData") ||
3142 !strcmp(commandbuffer,
"|RtmpSampleAccess")) {
3163 }
while (buf_temp - buf <
size);
3181 }
else if (ret < 0) {
3183 }
else if (ret == 1) {
3201#define OFFSET(x) offsetof(RTMPContext, x)
3202#define DEC AV_OPT_FLAG_DECODING_PARAM
3203#define ENC AV_OPT_FLAG_ENCODING_PARAM
3207 {
"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},
3210 {
"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},
3211 {
"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},
3212 {
"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"},
3215 {
"recorded",
"recorded stream", 0,
AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0,
DEC, .unit =
"rtmp_live"},
3216 {
"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},
3218 {
"rtmp_subscribe",
"Name of live stream to subscribe to. Defaults to rtmp_playpath.",
OFFSET(subscribe),
AV_OPT_TYPE_STRING, {.str =
NULL }, 0, 0,
DEC},
3220 {
"rtmp_swfsize",
"Size of the decompressed SWF file, required for SWFVerification.",
OFFSET(swfsize),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX,
DEC},
3224 {
"rtmp_listen",
"Listen for incoming rtmp connections",
OFFSET(listen),
AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX,
DEC, .unit =
"rtmp_listen" },
3225 {
"listen",
"Listen for incoming rtmp connections",
OFFSET(listen),
AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX,
DEC, .unit =
"rtmp_listen" },
3227 {
"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" },
3231#define RTMP_PROTOCOL_0(flavor)
3232#define RTMP_PROTOCOL_1(flavor) \
3233static const AVClass flavor##_class = { \
3234 .class_name = #flavor, \
3235 .item_name = av_default_item_name, \
3236 .option = rtmp_options, \
3237 .version = LIBAVUTIL_VERSION_INT, \
3240const URLProtocol ff_##flavor##_protocol = { \
3242 .url_open2 = rtmp_open, \
3243 .url_read = rtmp_read, \
3244 .url_read_seek = rtmp_seek, \
3245 .url_read_pause = rtmp_pause, \
3246 .url_write = rtmp_write, \
3247 .url_close = rtmp_close, \
3248 .priv_data_size = sizeof(RTMPContext), \
3249 .flags = URL_PROTOCOL_FLAG_NETWORK, \
3250 .priv_data_class= &flavor##_class, \
3252#define RTMP_PROTOCOL_2(flavor, enabled) \
3253 RTMP_PROTOCOL_ ## enabled(flavor)
3254#define RTMP_PROTOCOL_3(flavor, config) \
3255 RTMP_PROTOCOL_2(flavor, config)
3256#define RTMP_PROTOCOL(flavor, uppercase) \
3257 RTMP_PROTOCOL_3(flavor, CONFIG_ ## uppercase ## _PROTOCOL)
static struct AVMD5 * md5
static uint8_t hash[HASH_SIZE]
static AVDictionary * opts
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.
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
int ffurl_close(URLContext *h)
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.
#define AVIO_FLAG_READ
read-only
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
#define AVIO_FLAG_WRITE
write-only
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
static void BS_FUNC skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
static av_always_inline int bytestream2_tell_p(const PutByteContext *p)
static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, uint8_t *dst, unsigned int size)
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
static av_always_inline void bytestream2_skip_p(PutByteContext *p, unsigned int size)
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
static av_always_inline unsigned int bytestream2_copy_buffer(PutByteContext *p, GetByteContext *g, unsigned int size)
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, const uint8_t *src, unsigned int size)
#define flags(name, subs,...)
#define i(width, name, range_min, range_max)
channel
Use these values when setting the channel map with ebur128_set_channel().
@ FLV_HEADER_FLAG_HASVIDEO
@ FLV_HEADER_FLAG_HASAUDIO
@ AMF_DATA_TYPE_MIXEDARRAY
#define AMF_END_OF_OBJECT
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ 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...
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ 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...
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.
char * av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
Encode data to base64 and null-terminate.
#define AV_BASE64_SIZE(x)
Calculate the output size needed to base64-encode x bytes to a null-terminated string.
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
#define AV_DICT_MATCH_CASE
Only get an entry with exact-case key match.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
#define AVERROR_EOF
End of file.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
void av_md5_init(AVMD5 *ctx)
Initialize MD5 hashing.
void av_md5_final(AVMD5 *ctx, uint8_t *dst)
Finish hashing and output digest value.
struct AVMD5 * av_md5_alloc(void)
Allocate an AVMD5 context.
void av_md5_update(AVMD5 *ctx, const uint8_t *src, size_t len)
Update hash value.
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate an array through a pointer to a pointer.
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,...
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 av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags)
static av_always_inline uint64_t av_double2int(double f)
Reinterpret a double as a 64-bit integer.
static const char signature[]
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Public header for MD5 hash function implementation.
Memory handling functions.
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.
#define RTMP_CLIENT_PLATFORM
emulated Flash client version - 9.0.124.2 on Linux
#define RTMP_DEFAULT_PORT
#define RTMPS_DEFAULT_PORT
#define RTMP_HANDSHAKE_PACKET_SIZE
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.
int ff_rtmpe_gen_pub_key(URLContext *h, uint8_t *buf)
Initialize the Diffie-Hellmann context and generate the public key.
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_rtmpe_encrypt_sig(URLContext *h, uint8_t *sig, const uint8_t *digest, int type)
Encrypt the signature.
int ff_rtmpe_update_keystream(URLContext *h)
Update the keystream and set RC4 keys for encryption.
void ff_amf_write_string(uint8_t **dst, const char *str)
Write string in AMF format to buffer.
void ff_amf_write_null(uint8_t **dst)
Write AMF NULL value to buffer.
void ff_amf_write_number(uint8_t **dst, double val)
Write number in AMF format to buffer.
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.
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.
void ff_amf_write_object_start(uint8_t **dst)
Write marker for AMF object to buffer.
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 ff_amf_get_string(GetByteContext *bc, uint8_t *str, int strsize, int *length)
Get AMF string value.
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.
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.
int ff_amf_read_null(GetByteContext *bc)
Read AMF NULL value.
void ff_amf_write_array_start(uint8_t **dst, uint32_t length)
Write marker and length for AMF array to 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.
void ff_amf_write_bool(uint8_t **dst, int val)
Write boolean value in AMF format to buffer.
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 ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type, int timestamp, int size)
Create new RTMP packet with given attributes.
void ff_rtmp_packet_destroy(RTMPPacket *pkt)
Free RTMP packet.
int ff_amf_match_string(const uint8_t *data, int size, const char *str)
Match AMF string with a NULL-terminated string.
void ff_amf_write_object_end(uint8_t **dst)
Write marker for end of AMF object to buffer.
void ff_amf_write_field_name(uint8_t **dst, const char *str)
Write string used as field name in AMF object to buffer.
int ff_amf_read_string(GetByteContext *bc, uint8_t *str, int strsize, int *length)
Read AMF string value.
int ff_amf_read_number(GetByteContext *bc, double *val)
Read AMF number value.
@ RTMP_AUDIO_CHANNEL
channel for audio data
@ RTMP_NETWORK_CHANNEL
channel for network-related messages (bandwidth report, ping, etc)
@ RTMP_VIDEO_CHANNEL
channel for video data
@ RTMP_SYSTEM_CHANNEL
channel for sending server control messages
@ RTMP_SOURCE_CHANNEL
channel for a/v invokes
void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
Print information and contents of RTMP packet.
@ RTMP_PT_USER_CONTROL
user control
@ RTMP_PT_NOTIFY
some notification
@ RTMP_PT_CHUNK_SIZE
chunk size change
@ RTMP_PT_INVOKE
invoke some stream action
@ RTMP_PT_BYTES_READ
number of bytes read
@ RTMP_PT_SET_PEER_BW
peer bandwidth
@ RTMP_PT_WINDOW_ACK_SIZE
window acknowledgement size
@ RTMP_PT_VIDEO
video packet
@ RTMP_PT_METADATA
FLV metadata.
@ RTMP_PT_AUDIO
audio packet
static int handle_notify(URLContext *s, RTMPPacket *pkt)
static const AVOption rtmp_options[]
static int rtmp_read(URLContext *s, uint8_t *buf, int size)
static int read_number_result(RTMPPacket *pkt, double *number)
Read the AMF_NUMBER response ("_result") to a function call (e.g.
static int rtmp_calc_swfhash(URLContext *s)
static int gen_buffer_time(URLContext *s, RTMPContext *rt)
Generate client buffer time and send it to the server.
#define SERVER_KEY_OPEN_PART_LEN
length of partial key used for first server digest signing
static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
static int gen_publish(URLContext *s, RTMPContext *rt)
Generate 'publish' call and send it to the server.
static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
static int rtmp_send_hs_packet(RTMPContext *rt, uint32_t first_int, uint32_t second_int, char *arraydata, int size)
static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
static int handle_set_peer_bw(URLContext *s, RTMPPacket *pkt)
static int gen_get_stream_length(URLContext *s, RTMPContext *rt)
Generate 'getStreamLength' call and send it to the server.
static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset, char **tracked_method)
static const uint8_t rtmp_server_key[]
Key used for RTMP server digest signing.
static int rtmp_close(URLContext *h)
static int read_connect(URLContext *s, RTMPContext *rt)
static int add_tracked_method(RTMPContext *rt, const char *name, int id)
static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
rtmp handshake server side
#define FLASHVER_MAX_LENGTH
static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
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...
static int write_begin(URLContext *s)
static int rtmp_receive_hs_packet(RTMPContext *rt, uint32_t *first_int, uint32_t *second_int, char *arraydata, int size)
static int gen_swf_verification(URLContext *s, RTMPContext *rt)
Generate SWF verification message and send it to the server.
static int handle_invoke(URLContext *s, RTMPPacket *pkt)
static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
static int gen_release_stream(URLContext *s, RTMPContext *rt)
Generate 'releaseStream' call and send it to the server.
static int rtmp_pause(void *opaque, int pause)
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 append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
static int gen_create_stream(URLContext *s, RTMPContext *rt)
Generate 'createStream' call and send it to the server.
static int handle_connect_error(URLContext *s, const char *desc)
static int64_t rtmp_seek(void *opaque, int stream_index, int64_t timestamp, int flags)
static int handle_window_ack_size(URLContext *s, RTMPPacket *pkt)
ClientState
RTMP protocol handler state.
@ STATE_STOPPED
the broadcast has been stopped
@ STATE_SENDING
received a play command (for output)
@ STATE_PUBLISHING
client has started sending multimedia data to server (for output)
@ STATE_HANDSHAKED
client has performed handshake
@ STATE_RECEIVING
received a publish command (for input)
@ STATE_SEEKING
client has started the seek operation. Back on STATE_PLAYING when the time comes
@ STATE_FCPUBLISH
client FCPublishing stream (for output)
@ STATE_PLAYING
client has started receiving multimedia data from server
static const uint8_t rtmp_player_key[]
Client key used for digest signing.
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 do_adobe_auth(RTMPContext *rt, const char *user, const char *salt, const char *opaque, const char *challenge)
static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
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 (...
#define RTMP_CTRL_ABORT_MESSAGE
static size_t zstrlen(const char *c)
static int gen_check_bw(URLContext *s, RTMPContext *rt)
Generate check bandwidth message and send it to the server.
static int gen_window_ack_size(URLContext *s, RTMPContext *rt)
Generate window acknowledgement size message and send it to the server.
static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
Generate ping reply and send it to the server.
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 void free_tracked_methods(RTMPContext *rt)
static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt, const char *subscribe)
static void del_tracked_method(RTMPContext *rt, int index)
static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt, uint8_t *buf)
static int gen_delete_stream(URLContext *s, RTMPContext *rt)
Generate 'deleteStream' call and send it to the server.
static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
Generate 'FCUnpublish' call and send it to the server.
static int gen_connect(URLContext *s, RTMPContext *rt)
Generate 'connect' call and send it to the server.
static int rtmp_handshake(URLContext *s, RTMPContext *rt)
Perform handshake with the server by means of exchanging pseudorandom data signed with HMAC-SHA2 dige...
#define RTMP_PKTDATA_DEFAULT_SIZE
static int write_status(URLContext *s, RTMPPacket *pkt, const char *status, const char *description, const char *details)
static int update_offset(RTMPContext *rt, int size)
static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
Generate 'FCPublish' call and send it to the server.
static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **opts)
Open RTMP connection and verify that the stream can be played.
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 int gen_pause(URLContext *s, RTMPContext *rt, int pause, uint32_t timestamp)
Generate a pause packet that either pauses or unpauses the current stream.
static int rtmp_validate_digest(uint8_t *buf, int off)
Verify that the received server response has the expected digest value.
static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
#define PLAYER_KEY_OPEN_PART_LEN
length of partial key used for first client digest signing
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
static int handle_user_control(URLContext *s, RTMPPacket *pkt)
#define RTMP_PROTOCOL(flavor, uppercase)
static const uint8_t header[24]
double strtod(const char *, char **)
Describe the class of an AVClass context structure.
Context structure for the Lagged Fibonacci PRNG.
const uint8_t * buffer_end
RTMPPacket * prev_pkt[2]
packet history used when reading and sending packets ([0] for reading, [1] for writing)
int nb_streamid
The next stream id to return on createStream calls.
int encrypted
use an encrypted connection (RTMPE only)
char * swfverify
URL to player swf file, compute hash/size automatically.
int has_video
presence of video data
RTMPPacket out_pkt
rtmp packet, created from flv a/v or metadata (for output)
uint64_t bytes_read
number of bytes read from server
TrackedMethod * tracked_methods
tracked methods buffer
uint8_t * flv_data
buffer with data for demuxer
int listen_timeout
listen timeout to wait for new connections
int swfsize
size of the decompressed SWF file
int max_sent_unacked
max unacked sent bytes
int nb_prev_pkt[2]
number of elements in prev_pkt
char * conn
append arbitrary AMF data to the Connect message
char * pageurl
url of the web page
int client_buffer_time
client buffer time in ms
int skip_bytes
number of bytes to skip from the input FLV stream in the next write call
char * playpath
stream identifier to play (with possible "mp4:" prefix)
int received_metadata
Indicates if we have received metadata about the streams.
char * flashver
version of the flash plugin
int is_input
input/output flag
int nb_tracked_methods
number of tracked methods
int flv_off
number of bytes read from current buffer
uint8_t flv_header[RTMP_HEADER]
partial incoming flv packet header
char * app
name of application
char * enhanced_codecs
codec list in enhanced rtmp
uint64_t last_bytes_read
number of bytes read last reported to server
char * swfurl
url of the swf player
int out_chunk_size
size of the chunks outgoing RTMP packets are divided into
int flv_nb_packets
number of flv packets published
int stream_id
ID assigned by the server for the stream.
int flush_interval
number of packets flushed in the same request (RTMPT only)
int listen
listen mode flag
int tcp_nodelay
Use TCP_NODELAY to disable Nagle's algorithm if set to 1.
int has_audio
presence of audio data
char swfverification[42]
hash of the SWF verification
double duration
Duration of the stream in seconds as returned by the server (only valid if non-zero)
int flv_header_bytes
number of initialized bytes in flv_header
int flv_size
current buffer size
int tracked_methods_size
size of the tracked methods buffer
ClientState state
current state
int in_chunk_size
size of the chunks incoming RTMP packets are divided into
char * tcurl
url of the target stream
uint32_t receive_report_size
number of bytes after which we should report the number of received bytes to the peer
int nb_invokes
keeps track of invoke messages
char * subscribe
name of live stream to subscribe
URLContext * stream
TCP stream used in interactions with RTMP server.
int swfhash_len
length of the SHA256 hash
int live
0: recorded, -1: live, -2: both
char * swfhash
SHA256 hash of the decompressed SWF file (32 bytes)
uint32_t last_timestamp
last timestamp received in a packet
structure for holding RTMP packets
int size
packet payload size
uint32_t extra
probably an additional channel ID used during streaming data
RTMPPacketType type
packet payload type
uint32_t timestamp
packet full timestamp
uint8_t * data
packet payload
int channel_id
RTMP channel ID (nothing to do with audio/video channels though)
int max_packet_size
if non zero, the stream is packetized with this max packet size
static const uint8_t encrypted[]
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
unbuffered private I/O API
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 ffurl_write(URLContext *h, const uint8_t *buf, int size)
Write size bytes from buf to the resource accessed by h.
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.
static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
static void copy(const float *p1, float *p2, const int length)