81 #define PLAYER_KEY_OPEN_PART_LEN 30
83 static const uint8_t rtmp_player_key[] = {
84 'G',
'e',
'n',
'u',
'i',
'n',
'e',
' ',
'A',
'd',
'o',
'b',
'e',
' ',
85 'F',
'l',
'a',
's',
'h',
' ',
'P',
'l',
'a',
'y',
'e',
'r',
' ',
'0',
'0',
'1',
87 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
88 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
89 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
92 #define SERVER_KEY_OPEN_PART_LEN 36
94 static const uint8_t rtmp_server_key[] = {
95 'G',
'e',
'n',
'u',
'i',
'n',
'e',
' ',
'A',
'd',
'o',
'b',
'e',
' ',
96 'F',
'l',
'a',
's',
'h',
' ',
'M',
'e',
'd',
'i',
'a',
' ',
97 'S',
'e',
'r',
'v',
'e',
'r',
' ',
'0',
'0',
'1',
99 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
100 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
101 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
108 const char *host,
int port)
297 bytestream_put_be16(&p, 3);
298 bytestream_put_be32(&p, 1);
299 bytestream_put_be32(&p, 256);
339 bytestream_put_be16(&p, 7);
361 #define HMAC_IPAD_VAL 0x36
362 #define HMAC_OPAD_VAL 0x5C
376 const uint8_t *key,
int keylen, uint8_t *dst)
379 uint8_t hmac_buf[64+32] = {0};
385 memcpy(hmac_buf, key, keylen);
391 for (i = 0; i < 64; i++)
404 for (i = 0; i < 64; i++)
422 int i, digest_pos = 0;
424 for (i = 8; i < 12; i++)
425 digest_pos += buf[i];
426 digest_pos = (digest_pos % 728) + 12;
443 int i, digest_pos = 0;
446 for (i = 0; i < 4; i++)
447 digest_pos += buf[i + off];
448 digest_pos = (digest_pos % 728) + off + 4;
453 if (!memcmp(digest, buf + digest_pos, 32))
478 int server_pos, client_pos;
502 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
504 if (rt->
is_input && serverdata[5] >= 3) {
532 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
552 const uint8_t *data_end = pkt->
data + pkt->
size;
560 if (pkt->
size != 4) {
562 "Chunk size change packet is not 4 bytes long (%d)\n", pkt->
size);
582 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
595 "description", tmpstr,
sizeof(tmpstr)))
617 if (!pkt->
data[10]) {
626 if (pkt->
data[10] || pkt->
data[19] != 5 || pkt->
data[20]) {
640 const uint8_t* ptr = pkt->
data + 11;
643 for (i = 0; i < 2; i++) {
650 "level", tmpstr,
sizeof(tmpstr));
651 if (!t && !strcmp(tmpstr,
"error")) {
653 "description", tmpstr,
sizeof(tmpstr)))
658 "code", tmpstr,
sizeof(tmpstr));
661 if (!t && !strcmp(tmpstr,
"NetStream.Play.UnpublishNotify")) rt->
state =
STATE_STOPPED;
687 uint32_t ts, cts, pts=0;
735 bytestream_put_byte(&p, rpkt.
type);
736 bytestream_put_be24(&p, rpkt.
size);
737 bytestream_put_be24(&p, ts);
738 bytestream_put_byte(&p, ts >> 24);
739 bytestream_put_be24(&p, 0);
741 bytestream_put_be32(&p, 0);
752 while (next - rpkt.
data < rpkt.
size - 11) {
754 size = bytestream_get_be24(&next);
756 cts = bytestream_get_be24(&next);
757 cts |= bytestream_get_byte(&next) << 24;
762 bytestream_put_be24(&p, ts);
763 bytestream_put_byte(&p, ts >> 24);
764 next += size + 3 + 4;
805 char proto[8], hostname[256], path[1024], *fname;
812 av_url_split(proto,
sizeof(proto),
NULL, 0, hostname,
sizeof(hostname), &port,
832 if (!strncmp(path,
"/ondemand/", 10)) {
834 memcpy(rt->
app,
"ondemand", 9);
836 char *p = strchr(path + 1,
'/');
841 char *c = strchr(p + 1,
':');
842 fname = strchr(p + 1,
'/');
843 if (!fname || c < fname) {
852 if (!strchr(fname,
':') &&
853 (!strcmp(fname + strlen(fname) - 4,
".f4v") ||
854 !strcmp(fname + strlen(fname) - 4,
".mp4"))) {
871 }
while (ret == EAGAIN);
900 int orig_size =
size;
906 if (data_left >= size) {
927 int size_temp =
size;
928 int pktsize, pkttype;
930 const uint8_t *buf_temp = buf;
950 pkttype = bytestream_get_byte(&header);
951 pktsize = bytestream_get_be24(&header);
952 ts = bytestream_get_be24(&header);
953 ts |= bytestream_get_byte(&header) << 24;
954 bytestream_get_be24(&header);
993 }
while (buf_temp - buf < size);
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.
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
int ff_amf_match_string(const uint8_t *data, int size, const char *str)
Match AMF string with a NULL-terminated string.
static int rtmp_read(URLContext *s, uint8_t *buf, int size)
AV_WL32 AV_WL24 AV_WL16 AV_WB32 AV_WB24 AV_RB16
#define URL_PROTOCOL_FLAG_NETWORK
void av_sha_update(AVSHA *ctx, const uint8_t *data, unsigned int len)
Update hash value.
AV_WL32 AV_WL24 AV_WL16 AV_RB32
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
int av_sha_init(AVSHA *ctx, int bits)
Initialize SHA-1 or SHA-2 hashing.
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.
int is_streamed
true if streamed (no seek possible), default = false
client has sent all needed commands and waits for server reply
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
#define AV_LOG_WARNING
Something somehow does not look correct.
static void gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
Generate ping reply and send it to the server.
AVIOInterruptCB interrupt_callback
#define AVIO_FLAG_WRITE
write-only
int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
Calculate number of bytes taken by first AMF entry in data.
struct RTMPContext RTMPContext
protocol handler context
int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket *prev_pkt)
Read RTMP packet sent by the server.
URLContext * stream
TCP stream used in interactions with RTMP server.
void * av_realloc(void *ptr, size_t size)
Allocate or reallocate a block of memory.
#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
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
client releasing stream before publish it (for output)
static void 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 void gen_publish(URLContext *s, RTMPContext *rt)
Generate 'publish' call and send it to the server.
void ff_amf_write_string(uint8_t **dst, const char *str)
Write string in AMF format to buffer.
static void gen_create_stream(URLContext *s, RTMPContext *rt)
Generate 'createStream' call and send it to the server.
void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
Print information and contents of RTMP packet.
int nb_invokes
keeps track of invoke messages
#define AVERROR_EOF
End of file.
int flv_size
current buffer size
static void copy(LZOContext *c, int cnt)
Copies bytes from input to output buffer with checking.
static int rtmp_handshake(URLContext *s, RTMPContext *rt)
Perform handshake with the server by means of exchanging pseudorandom data signed with HMAC-SHA2 dige...
void ff_amf_write_object_end(uint8_t **dst)
Write marker for end of AMF object to buffer.
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.
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
static void gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
Generate report on bytes read so far and send it to the server.
ClientState
RTMP protocol handler state.
client connected to server successfully
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_log(void *avcl, int level, const char *fmt,...)
static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
Generate 'FCPublish' call and send it to the server.
client has not done anything yet
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.
client has performed handshake
int create_stream_invoke
invoke id for the create stream command
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.
client has started sending multimedia data to server (for output)
void ff_rtmp_packet_destroy(RTMPPacket *pkt)
Free RTMP packet.
client has started receiving multimedia data from server
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 chunk_size
size of the chunks RTMP packets are divided into
#define RTMP_CLIENT_PLATFORM
emulated Flash client version - 9.0.124.2 on Linux
static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
Generate 'FCUnpublish' call and send it to the server.
int is_input
input/output flag
static const uint8_t rtmp_player_key[]
Client key used for digest signing.
static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, uint8_t *dst, unsigned int size)
the broadcast has been stopped
char playpath[256]
path to filename to play (with possible "mp4:" prefix)
static void gen_connect(URLContext *s, RTMPContext *rt, const char *proto, const char *host, int port)
Generate 'connect' call and send it to the server.
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.
static void gen_delete_stream(URLContext *s, RTMPContext *rt)
Generate 'deleteStream' call and send it to the server.
uint32_t bytes_read
number of bytes read from server
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
channel for sending server control messages
int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type, int timestamp, int size)
Create new RTMP packet with given attributes.
static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
Put HMAC-SHA2 digest of packet data (except for the bytes where this digest will be stored) into that...
int channel_id
RTMP channel ID (nothing to do with audio/video channels though)
uint8_t flv_header[11]
partial incoming flv packet header
RTMPPacket out_pkt
rtmp packet, created from flv a/v or metadata (for output)
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)
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
static void gen_play(URLContext *s, RTMPContext *rt)
Generate 'play' call and send it to the server, then ping the server to start actual playing...
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.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
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. ...
void av_cold av_lfg_init(AVLFG *c, unsigned int seed)
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...
char * filename
specified URL
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
URLProtocol ff_rtmp_protocol
void ff_amf_write_number(uint8_t **dst, double val)
Write number in AMF format to buffer.
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 (...
uint8_t * flv_data
buffer with data for demuxer
void ff_amf_write_object_start(uint8_t **dst)
Write marker for AMF object to buffer.
static void gen_release_stream(URLContext *s, RTMPContext *rt)
Generate 'releaseStream' call and send it to the server.
int max_packet_size
if non zero, the stream is packetized with this max packet size
structure for holding RTMP packets
unbuffered private I/O API
invoke some stream action
uint32_t client_report_size
number of bytes after which client should report to server