2 * RTMP network protocol
3 * Copyright (c) 2009 Kostya Shishkov
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "libavcodec/bytestream.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/intfloat.h"
30 #include "libavutil/lfg.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/sha.h"
45 #define APP_MAX_LENGTH 128
46 #define PLAYPATH_MAX_LENGTH 256
47 #define TCURL_MAX_LENGTH 512
48 #define FLASHVER_MAX_LENGTH 64
50 /** RTMP protocol handler state */
52 STATE_START, ///< client has not done anything yet
53 STATE_HANDSHAKED, ///< client has performed handshake
54 STATE_RELEASING, ///< client releasing stream before publish it (for output)
55 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
56 STATE_CONNECTING, ///< client connected to server successfully
57 STATE_READY, ///< client has sent all needed commands and waits for server reply
58 STATE_PLAYING, ///< client has started receiving multimedia data from server
59 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
60 STATE_STOPPED, ///< the broadcast has been stopped
63 /** protocol handler context */
64 typedef struct RTMPContext {
66 URLContext* stream; ///< TCP stream used in interactions with RTMP server
67 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
68 int chunk_size; ///< size of the chunks RTMP packets are divided into
69 int is_input; ///< input/output flag
70 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
71 int live; ///< 0: recorded, -1: live, -2: both
72 char *app; ///< name of application
73 char *conn; ///< append arbitrary AMF data to the Connect message
74 ClientState state; ///< current state
75 int main_channel_id; ///< an additional channel ID which is used for some invocations
76 uint8_t* flv_data; ///< buffer with data for demuxer
77 int flv_size; ///< current buffer size
78 int flv_off; ///< number of bytes read from current buffer
79 int flv_nb_packets; ///< number of flv packets published
80 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
81 uint32_t client_report_size; ///< number of bytes after which client should report to server
82 uint32_t bytes_read; ///< number of bytes read from server
83 uint32_t last_bytes_read; ///< number of bytes read last reported to server
84 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
85 uint8_t flv_header[11]; ///< partial incoming flv packet header
86 int flv_header_bytes; ///< number of initialized bytes in flv_header
87 int nb_invokes; ///< keeps track of invoke messages
88 int create_stream_invoke; ///< invoke id for the create stream command
89 char* tcurl; ///< url of the target stream
90 char* flashver; ///< version of the flash plugin
91 char* swfurl; ///< url of the swf player
92 int server_bw; ///< server bandwidth
93 int client_buffer_time; ///< client buffer time in ms
94 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
97 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
98 /** Client key used for digest signing */
99 static const uint8_t rtmp_player_key[] = {
100 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
101 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
103 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
104 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
105 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
108 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
109 /** Key used for RTMP server digest signing */
110 static const uint8_t rtmp_server_key[] = {
111 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
112 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
113 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
115 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
116 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
117 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
120 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
125 /* The type must be B for Boolean, N for number, S for string, O for
126 * object, or Z for null. For Booleans the data must be either 0 or 1 for
127 * FALSE or TRUE, respectively. Likewise for Objects the data must be
128 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
129 * may be named, by prefixing the type with 'N' and specifying the name
130 * before the value (ie. NB:myFlag:1). This option may be used multiple times
131 * to construct arbitrary AMF sequences. */
132 if (param[0] && param[1] == ':') {
135 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
138 value = strchr(field, ':');
144 if (!field || !value)
147 ff_amf_write_field_name(p, field);
154 ff_amf_write_bool(p, value[0] != '0');
157 ff_amf_write_string(p, value);
160 ff_amf_write_number(p, strtod(value, NULL));
163 ff_amf_write_null(p);
167 ff_amf_write_object_start(p);
169 ff_amf_write_object_end(p);
179 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
180 return AVERROR(EINVAL);
184 * Generate 'connect' call and send it to the server.
186 static int gen_connect(URLContext *s, RTMPContext *rt)
192 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
198 ff_amf_write_string(&p, "connect");
199 ff_amf_write_number(&p, ++rt->nb_invokes);
200 ff_amf_write_object_start(&p);
201 ff_amf_write_field_name(&p, "app");
202 ff_amf_write_string(&p, rt->app);
205 ff_amf_write_field_name(&p, "type");
206 ff_amf_write_string(&p, "nonprivate");
208 ff_amf_write_field_name(&p, "flashVer");
209 ff_amf_write_string(&p, rt->flashver);
212 ff_amf_write_field_name(&p, "swfUrl");
213 ff_amf_write_string(&p, rt->swfurl);
216 ff_amf_write_field_name(&p, "tcUrl");
217 ff_amf_write_string(&p, rt->tcurl);
219 ff_amf_write_field_name(&p, "fpad");
220 ff_amf_write_bool(&p, 0);
221 ff_amf_write_field_name(&p, "capabilities");
222 ff_amf_write_number(&p, 15.0);
224 /* Tell the server we support all the audio codecs except
225 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
226 * which are unused in the RTMP protocol implementation. */
227 ff_amf_write_field_name(&p, "audioCodecs");
228 ff_amf_write_number(&p, 4071.0);
229 ff_amf_write_field_name(&p, "videoCodecs");
230 ff_amf_write_number(&p, 252.0);
231 ff_amf_write_field_name(&p, "videoFunction");
232 ff_amf_write_number(&p, 1.0);
234 ff_amf_write_object_end(&p);
237 char *param = rt->conn;
239 // Write arbitrary AMF data to the Connect message.
240 while (param != NULL) {
242 param += strspn(param, " ");
245 sep = strchr(param, ' ');
248 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
249 // Invalid AMF parameter.
250 ff_rtmp_packet_destroy(&pkt);
261 pkt.data_size = p - pkt.data;
263 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
265 ff_rtmp_packet_destroy(&pkt);
271 * Generate 'releaseStream' call and send it to the server. It should make
272 * the server release some channel for media streams.
274 static int gen_release_stream(URLContext *s, RTMPContext *rt)
280 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
281 0, 29 + strlen(rt->playpath))) < 0)
284 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
286 ff_amf_write_string(&p, "releaseStream");
287 ff_amf_write_number(&p, ++rt->nb_invokes);
288 ff_amf_write_null(&p);
289 ff_amf_write_string(&p, rt->playpath);
291 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
293 ff_rtmp_packet_destroy(&pkt);
299 * Generate 'FCPublish' call and send it to the server. It should make
300 * the server preapare for receiving media streams.
302 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
308 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
309 0, 25 + strlen(rt->playpath))) < 0)
312 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
314 ff_amf_write_string(&p, "FCPublish");
315 ff_amf_write_number(&p, ++rt->nb_invokes);
316 ff_amf_write_null(&p);
317 ff_amf_write_string(&p, rt->playpath);
319 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
321 ff_rtmp_packet_destroy(&pkt);
327 * Generate 'FCUnpublish' call and send it to the server. It should make
328 * the server destroy stream.
330 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
336 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
337 0, 27 + strlen(rt->playpath))) < 0)
340 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
342 ff_amf_write_string(&p, "FCUnpublish");
343 ff_amf_write_number(&p, ++rt->nb_invokes);
344 ff_amf_write_null(&p);
345 ff_amf_write_string(&p, rt->playpath);
347 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
349 ff_rtmp_packet_destroy(&pkt);
355 * Generate 'createStream' call and send it to the server. It should make
356 * the server allocate some channel for media streams.
358 static int gen_create_stream(URLContext *s, RTMPContext *rt)
364 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
366 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
371 ff_amf_write_string(&p, "createStream");
372 ff_amf_write_number(&p, ++rt->nb_invokes);
373 ff_amf_write_null(&p);
374 rt->create_stream_invoke = rt->nb_invokes;
376 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
378 ff_rtmp_packet_destroy(&pkt);
385 * Generate 'deleteStream' call and send it to the server. It should make
386 * the server remove some channel for media streams.
388 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
394 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
396 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
401 ff_amf_write_string(&p, "deleteStream");
402 ff_amf_write_number(&p, ++rt->nb_invokes);
403 ff_amf_write_null(&p);
404 ff_amf_write_number(&p, rt->main_channel_id);
406 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
408 ff_rtmp_packet_destroy(&pkt);
414 * Generate client buffer time and send it to the server.
416 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
422 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
427 bytestream_put_be16(&p, 3);
428 bytestream_put_be32(&p, rt->main_channel_id);
429 bytestream_put_be32(&p, rt->client_buffer_time);
431 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
433 ff_rtmp_packet_destroy(&pkt);
439 * Generate 'play' call and send it to the server, then ping the server
440 * to start actual playing.
442 static int gen_play(URLContext *s, RTMPContext *rt)
448 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
450 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
451 0, 29 + strlen(rt->playpath))) < 0)
454 pkt.extra = rt->main_channel_id;
457 ff_amf_write_string(&p, "play");
458 ff_amf_write_number(&p, ++rt->nb_invokes);
459 ff_amf_write_null(&p);
460 ff_amf_write_string(&p, rt->playpath);
461 ff_amf_write_number(&p, rt->live);
463 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
465 ff_rtmp_packet_destroy(&pkt);
471 * Generate 'publish' call and send it to the server.
473 static int gen_publish(URLContext *s, RTMPContext *rt)
479 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
481 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
482 0, 30 + strlen(rt->playpath))) < 0)
485 pkt.extra = rt->main_channel_id;
488 ff_amf_write_string(&p, "publish");
489 ff_amf_write_number(&p, ++rt->nb_invokes);
490 ff_amf_write_null(&p);
491 ff_amf_write_string(&p, rt->playpath);
492 ff_amf_write_string(&p, "live");
494 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
496 ff_rtmp_packet_destroy(&pkt);
502 * Generate ping reply and send it to the server.
504 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
510 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
511 ppkt->timestamp + 1, 6)) < 0)
515 bytestream_put_be16(&p, 7);
516 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
517 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
519 ff_rtmp_packet_destroy(&pkt);
525 * Generate server bandwidth message and send it to the server.
527 static int gen_server_bw(URLContext *s, RTMPContext *rt)
533 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
538 bytestream_put_be32(&p, rt->server_bw);
539 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
541 ff_rtmp_packet_destroy(&pkt);
547 * Generate check bandwidth message and send it to the server.
549 static int gen_check_bw(URLContext *s, RTMPContext *rt)
555 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
560 ff_amf_write_string(&p, "_checkbw");
561 ff_amf_write_number(&p, ++rt->nb_invokes);
562 ff_amf_write_null(&p);
564 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
566 ff_rtmp_packet_destroy(&pkt);
572 * Generate report on bytes read so far and send it to the server.
574 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
580 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
585 bytestream_put_be32(&p, rt->bytes_read);
586 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
588 ff_rtmp_packet_destroy(&pkt);
593 //TODO: Move HMAC code somewhere. Eventually.
594 #define HMAC_IPAD_VAL 0x36
595 #define HMAC_OPAD_VAL 0x5C
598 * Calculate HMAC-SHA2 digest for RTMP handshake packets.
600 * @param src input buffer
601 * @param len input buffer length (should be 1536)
602 * @param gap offset in buffer where 32 bytes should not be taken into account
603 * when calculating digest (since it will be used to store that digest)
604 * @param key digest key
605 * @param keylen digest key length
606 * @param dst buffer where calculated digest will be stored (32 bytes)
608 static int rtmp_calc_digest(const uint8_t *src, int len, int gap,
609 const uint8_t *key, int keylen, uint8_t *dst)
612 uint8_t hmac_buf[64+32] = {0};
615 sha = av_mallocz(av_sha_size);
617 return AVERROR(ENOMEM);
620 memcpy(hmac_buf, key, keylen);
622 av_sha_init(sha, 256);
623 av_sha_update(sha,key, keylen);
624 av_sha_final(sha, hmac_buf);
626 for (i = 0; i < 64; i++)
627 hmac_buf[i] ^= HMAC_IPAD_VAL;
629 av_sha_init(sha, 256);
630 av_sha_update(sha, hmac_buf, 64);
632 av_sha_update(sha, src, len);
633 } else { //skip 32 bytes used for storing digest
634 av_sha_update(sha, src, gap);
635 av_sha_update(sha, src + gap + 32, len - gap - 32);
637 av_sha_final(sha, hmac_buf + 64);
639 for (i = 0; i < 64; i++)
640 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
641 av_sha_init(sha, 256);
642 av_sha_update(sha, hmac_buf, 64+32);
643 av_sha_final(sha, dst);
651 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
652 * will be stored) into that packet.
654 * @param buf handshake data (1536 bytes)
655 * @return offset to the digest inside input data
657 static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
659 int i, digest_pos = 0;
662 for (i = 8; i < 12; i++)
663 digest_pos += buf[i];
664 digest_pos = (digest_pos % 728) + 12;
666 ret = rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
667 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
676 * Verify that the received server response has the expected digest value.
678 * @param buf handshake data received from the server (1536 bytes)
679 * @param off position to search digest offset from
680 * @return 0 if digest is valid, digest position otherwise
682 static int rtmp_validate_digest(uint8_t *buf, int off)
684 int i, digest_pos = 0;
688 for (i = 0; i < 4; i++)
689 digest_pos += buf[i + off];
690 digest_pos = (digest_pos % 728) + off + 4;
692 ret = rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
693 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
698 if (!memcmp(digest, buf + digest_pos, 32))
704 * Perform handshake with the server by means of exchanging pseudorandom data
705 * signed with HMAC-SHA2 digest.
707 * @return 0 if handshake succeeds, negative value otherwise
709 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
712 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
713 3, // unencrypted data
714 0, 0, 0, 0, // client uptime
720 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
721 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
723 int server_pos, client_pos;
727 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
729 av_lfg_init(&rnd, 0xDEADC0DE);
730 // generate handshake packet - 1536 bytes of pseudorandom data
731 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
732 tosend[i] = av_lfg_get(&rnd) >> 24;
733 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1);
737 if ((ret = ffurl_write(rt->stream, tosend,
738 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
739 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
743 if ((ret = ffurl_read_complete(rt->stream, serverdata,
744 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
745 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
749 if ((ret = ffurl_read_complete(rt->stream, clientdata,
750 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
751 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
755 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
756 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
758 if (rt->is_input && serverdata[5] >= 3) {
759 server_pos = rtmp_validate_digest(serverdata + 1, 772);
764 server_pos = rtmp_validate_digest(serverdata + 1, 8);
769 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
774 ret = rtmp_calc_digest(tosend + 1 + client_pos, 32, 0, rtmp_server_key,
775 sizeof(rtmp_server_key), digest);
779 ret = rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
784 if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
785 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
789 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
790 tosend[i] = av_lfg_get(&rnd) >> 24;
791 ret = rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
792 rtmp_player_key, sizeof(rtmp_player_key),
797 ret = rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
799 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
803 // write reply back to the server
804 if ((ret = ffurl_write(rt->stream, tosend,
805 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
808 if ((ret = ffurl_write(rt->stream, serverdata + 1,
809 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
817 * Parse received packet and possibly perform some action depending on
818 * the packet contents.
819 * @return 0 for no errors, negative values for serious errors which prevent
820 * further communications, positive values for uncritical errors
822 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
825 const uint8_t *data_end = pkt->data + pkt->data_size;
829 ff_rtmp_packet_dump(s, pkt);
833 case RTMP_PT_CHUNK_SIZE:
834 if (pkt->data_size != 4) {
835 av_log(s, AV_LOG_ERROR,
836 "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
840 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->chunk_size,
841 rt->prev_pkt[1])) < 0)
843 rt->chunk_size = AV_RB32(pkt->data);
844 if (rt->chunk_size <= 0) {
845 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
848 av_log(s, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
851 t = AV_RB16(pkt->data);
853 if ((ret = gen_pong(s, rt, pkt)) < 0)
856 case RTMP_PT_CLIENT_BW:
857 if (pkt->data_size < 4) {
858 av_log(s, AV_LOG_ERROR,
859 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
863 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
864 rt->client_report_size = AV_RB32(pkt->data) >> 1;
866 case RTMP_PT_SERVER_BW:
867 rt->server_bw = AV_RB32(pkt->data);
868 if (rt->server_bw <= 0) {
869 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n", rt->server_bw);
870 return AVERROR(EINVAL);
872 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
875 //TODO: check for the messages sent for wrong state?
876 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
879 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
880 "description", tmpstr, sizeof(tmpstr)))
881 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
883 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
885 case STATE_HANDSHAKED:
887 if ((ret = gen_release_stream(s, rt)) < 0)
889 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
891 rt->state = STATE_RELEASING;
893 if ((ret = gen_server_bw(s, rt)) < 0)
895 rt->state = STATE_CONNECTING;
897 if ((ret = gen_create_stream(s, rt)) < 0)
900 case STATE_FCPUBLISH:
901 rt->state = STATE_CONNECTING;
903 case STATE_RELEASING:
904 rt->state = STATE_FCPUBLISH;
905 /* hack for Wowza Media Server, it does not send result for
906 * releaseStream and FCPublish calls */
907 if (!pkt->data[10]) {
908 int pkt_id = av_int2double(AV_RB64(pkt->data + 11));
909 if (pkt_id == rt->create_stream_invoke)
910 rt->state = STATE_CONNECTING;
912 if (rt->state != STATE_CONNECTING)
914 case STATE_CONNECTING:
915 //extract a number from the result
916 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
917 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
919 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
922 if ((ret = gen_play(s, rt)) < 0)
924 if ((ret = gen_buffer_time(s, rt)) < 0)
927 if ((ret = gen_publish(s, rt)) < 0)
930 rt->state = STATE_READY;
933 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
934 const uint8_t* ptr = pkt->data + 11;
937 for (i = 0; i < 2; i++) {
938 t = ff_amf_tag_size(ptr, data_end);
943 t = ff_amf_get_field_value(ptr, data_end,
944 "level", tmpstr, sizeof(tmpstr));
945 if (!t && !strcmp(tmpstr, "error")) {
946 if (!ff_amf_get_field_value(ptr, data_end,
947 "description", tmpstr, sizeof(tmpstr)))
948 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
951 t = ff_amf_get_field_value(ptr, data_end,
952 "code", tmpstr, sizeof(tmpstr));
953 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
954 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
955 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
956 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
957 } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
958 if ((ret = gen_check_bw(s, rt)) < 0)
964 /* Audio and Video packets are parsed in get_packet() */
967 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
974 * Interact with the server by receiving and sending RTMP packets until
975 * there is some significant data (media data or expected status notification).
977 * @param s reading context
978 * @param for_header non-zero value tells function to work until it
979 * gets notification from the server that playing has been started,
980 * otherwise function will work until some media data is received (or
982 * @return 0 for successful operation, negative value in case of error
984 static int get_packet(URLContext *s, int for_header)
986 RTMPContext *rt = s->priv_data;
991 uint32_t ts, cts, pts=0;
993 if (rt->state == STATE_STOPPED)
997 RTMPPacket rpkt = { 0 };
998 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
999 rt->chunk_size, rt->prev_pkt[0])) <= 0) {
1001 return AVERROR(EAGAIN);
1003 return AVERROR(EIO);
1006 rt->bytes_read += ret;
1007 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
1008 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
1009 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
1011 rt->last_bytes_read = rt->bytes_read;
1014 ret = rtmp_parse_result(s, rt, &rpkt);
1015 if (ret < 0) {//serious error in current packet
1016 ff_rtmp_packet_destroy(&rpkt);
1019 if (rt->state == STATE_STOPPED) {
1020 ff_rtmp_packet_destroy(&rpkt);
1023 if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
1024 ff_rtmp_packet_destroy(&rpkt);
1027 if (!rpkt.data_size || !rt->is_input) {
1028 ff_rtmp_packet_destroy(&rpkt);
1031 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
1032 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
1033 ts = rpkt.timestamp;
1035 // generate packet header and put data into buffer for FLV demuxer
1037 rt->flv_size = rpkt.data_size + 15;
1038 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
1039 bytestream_put_byte(&p, rpkt.type);
1040 bytestream_put_be24(&p, rpkt.data_size);
1041 bytestream_put_be24(&p, ts);
1042 bytestream_put_byte(&p, ts >> 24);
1043 bytestream_put_be24(&p, 0);
1044 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
1045 bytestream_put_be32(&p, 0);
1046 ff_rtmp_packet_destroy(&rpkt);
1048 } else if (rpkt.type == RTMP_PT_METADATA) {
1049 // we got raw FLV data, make it available for FLV demuxer
1051 rt->flv_size = rpkt.data_size;
1052 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
1053 /* rewrite timestamps */
1055 ts = rpkt.timestamp;
1056 while (next - rpkt.data < rpkt.data_size - 11) {
1058 data_size = bytestream_get_be24(&next);
1060 cts = bytestream_get_be24(&next);
1061 cts |= bytestream_get_byte(&next) << 24;
1066 bytestream_put_be24(&p, ts);
1067 bytestream_put_byte(&p, ts >> 24);
1068 next += data_size + 3 + 4;
1070 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
1071 ff_rtmp_packet_destroy(&rpkt);
1074 ff_rtmp_packet_destroy(&rpkt);
1078 static int rtmp_close(URLContext *h)
1080 RTMPContext *rt = h->priv_data;
1083 if (!rt->is_input) {
1084 rt->flv_data = NULL;
1085 if (rt->out_pkt.data_size)
1086 ff_rtmp_packet_destroy(&rt->out_pkt);
1087 if (rt->state > STATE_FCPUBLISH)
1088 ret = gen_fcunpublish_stream(h, rt);
1090 if (rt->state > STATE_HANDSHAKED)
1091 ret = gen_delete_stream(h, rt);
1093 av_freep(&rt->flv_data);
1094 ffurl_close(rt->stream);
1099 * Open RTMP connection and verify that the stream can be played.
1101 * URL syntax: rtmp://server[:port][/app][/playpath]
1102 * where 'app' is first one or two directories in the path
1103 * (e.g. /ondemand/, /flash/live/, etc.)
1104 * and 'playpath' is a file name (the rest of the path,
1105 * may be prefixed with "mp4:")
1107 static int rtmp_open(URLContext *s, const char *uri, int flags)
1109 RTMPContext *rt = s->priv_data;
1110 char proto[8], hostname[256], path[1024], *fname;
1114 AVDictionary *opts = NULL;
1117 rt->is_input = !(flags & AVIO_FLAG_WRITE);
1119 av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
1120 path, sizeof(path), s->filename);
1122 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
1123 if (!strcmp(proto, "rtmpts"))
1124 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
1126 /* open the http tunneling connection */
1127 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
1128 } else if (!strcmp(proto, "rtmps")) {
1129 /* open the tls connection */
1131 port = RTMPS_DEFAULT_PORT;
1132 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
1134 /* open the tcp connection */
1136 port = RTMP_DEFAULT_PORT;
1137 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
1140 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
1141 &s->interrupt_callback, &opts)) < 0) {
1142 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
1146 rt->state = STATE_START;
1147 if ((ret = rtmp_handshake(s, rt)) < 0)
1150 rt->chunk_size = 128;
1151 rt->state = STATE_HANDSHAKED;
1153 // Keep the application name when it has been defined by the user.
1156 rt->app = av_malloc(APP_MAX_LENGTH);
1158 ret = AVERROR(ENOMEM);
1162 //extract "app" part from path
1163 if (!strncmp(path, "/ondemand/", 10)) {
1165 memcpy(rt->app, "ondemand", 9);
1167 char *next = *path ? path + 1 : path;
1168 char *p = strchr(next, '/');
1173 // make sure we do not mismatch a playpath for an application instance
1174 char *c = strchr(p + 1, ':');
1175 fname = strchr(p + 1, '/');
1176 if (!fname || (c && c < fname)) {
1178 av_strlcpy(rt->app, path + 1, p - path);
1181 av_strlcpy(rt->app, path + 1, fname - path - 1);
1187 // The name of application has been defined by the user, override it.
1192 if (!rt->playpath) {
1193 int len = strlen(fname);
1195 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
1196 if (!rt->playpath) {
1197 ret = AVERROR(ENOMEM);
1201 if (!strchr(fname, ':') && len >= 4 &&
1202 (!strcmp(fname + len - 4, ".f4v") ||
1203 !strcmp(fname + len - 4, ".mp4"))) {
1204 memcpy(rt->playpath, "mp4:", 5);
1205 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
1206 fname[len - 4] = '\0';
1208 rt->playpath[0] = 0;
1210 strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5);
1214 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
1216 ret = AVERROR(ENOMEM);
1219 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
1220 port, "/%s", rt->app);
1223 if (!rt->flashver) {
1224 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
1225 if (!rt->flashver) {
1226 ret = AVERROR(ENOMEM);
1230 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
1231 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
1232 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
1234 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
1235 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
1239 rt->client_report_size = 1048576;
1241 rt->last_bytes_read = 0;
1242 rt->server_bw = 2500000;
1244 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
1245 proto, path, rt->app, rt->playpath);
1246 if ((ret = gen_connect(s, rt)) < 0)
1250 ret = get_packet(s, 1);
1251 } while (ret == EAGAIN);
1256 // generate FLV header for demuxer
1258 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
1260 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
1263 rt->flv_data = NULL;
1265 rt->skip_bytes = 13;
1268 s->max_packet_size = rt->stream->max_packet_size;
1273 av_dict_free(&opts);
1278 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
1280 RTMPContext *rt = s->priv_data;
1281 int orig_size = size;
1285 int data_left = rt->flv_size - rt->flv_off;
1287 if (data_left >= size) {
1288 memcpy(buf, rt->flv_data + rt->flv_off, size);
1289 rt->flv_off += size;
1292 if (data_left > 0) {
1293 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
1296 rt->flv_off = rt->flv_size;
1299 if ((ret = get_packet(s, 0)) < 0)
1305 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
1307 RTMPContext *rt = s->priv_data;
1308 int size_temp = size;
1309 int pktsize, pkttype;
1311 const uint8_t *buf_temp = buf;
1316 if (rt->skip_bytes) {
1317 int skip = FFMIN(rt->skip_bytes, size_temp);
1320 rt->skip_bytes -= skip;
1324 if (rt->flv_header_bytes < 11) {
1325 const uint8_t *header = rt->flv_header;
1326 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
1327 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
1328 rt->flv_header_bytes += copy;
1330 if (rt->flv_header_bytes < 11)
1333 pkttype = bytestream_get_byte(&header);
1334 pktsize = bytestream_get_be24(&header);
1335 ts = bytestream_get_be24(&header);
1336 ts |= bytestream_get_byte(&header) << 24;
1337 bytestream_get_be24(&header);
1338 rt->flv_size = pktsize;
1340 //force 12bytes header
1341 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
1342 pkttype == RTMP_PT_NOTIFY) {
1343 if (pkttype == RTMP_PT_NOTIFY)
1345 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
1348 //this can be a big packet, it's better to send it right here
1349 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
1350 pkttype, ts, pktsize)) < 0)
1353 rt->out_pkt.extra = rt->main_channel_id;
1354 rt->flv_data = rt->out_pkt.data;
1356 if (pkttype == RTMP_PT_NOTIFY)
1357 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
1360 if (rt->flv_size - rt->flv_off > size_temp) {
1361 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
1362 rt->flv_off += size_temp;
1365 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
1366 size_temp -= rt->flv_size - rt->flv_off;
1367 rt->flv_off += rt->flv_size - rt->flv_off;
1370 if (rt->flv_off == rt->flv_size) {
1373 if ((ret = ff_rtmp_packet_write(rt->stream, &rt->out_pkt,
1374 rt->chunk_size, rt->prev_pkt[1])) < 0)
1376 ff_rtmp_packet_destroy(&rt->out_pkt);
1379 rt->flv_header_bytes = 0;
1380 rt->flv_nb_packets++;
1382 } while (buf_temp - buf < size);
1384 if (rt->flv_nb_packets < rt->flush_interval)
1386 rt->flv_nb_packets = 0;
1388 /* set stream into nonblocking mode */
1389 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
1391 /* try to read one byte from the stream */
1392 ret = ffurl_read(rt->stream, &c, 1);
1394 /* switch the stream back into blocking mode */
1395 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
1397 if (ret == AVERROR(EAGAIN)) {
1398 /* no incoming data to handle */
1400 } else if (ret < 0) {
1402 } else if (ret == 1) {
1403 RTMPPacket rpkt = { 0 };
1405 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
1407 rt->prev_pkt[0], c)) <= 0)
1410 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
1413 ff_rtmp_packet_destroy(&rpkt);
1419 #define OFFSET(x) offsetof(RTMPContext, x)
1420 #define DEC AV_OPT_FLAG_DECODING_PARAM
1421 #define ENC AV_OPT_FLAG_ENCODING_PARAM
1423 static const AVOption rtmp_options[] = {
1424 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1425 {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {3000}, 0, INT_MAX, DEC|ENC},
1426 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1427 {"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1428 {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {10}, 0, INT_MAX, ENC},
1429 {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
1430 {"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
1431 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
1432 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"},
1433 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1434 {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1435 {"rtmp_tcurl", "URL of the target stream. Defaults to rtmp://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1439 static const AVClass rtmp_class = {
1440 .class_name = "rtmp",
1441 .item_name = av_default_item_name,
1442 .option = rtmp_options,
1443 .version = LIBAVUTIL_VERSION_INT,
1446 URLProtocol ff_rtmp_protocol = {
1448 .url_open = rtmp_open,
1449 .url_read = rtmp_read,
1450 .url_write = rtmp_write,
1451 .url_close = rtmp_close,
1452 .priv_data_size = sizeof(RTMPContext),
1453 .flags = URL_PROTOCOL_FLAG_NETWORK,
1454 .priv_data_class= &rtmp_class,
1457 static const AVClass rtmps_class = {
1458 .class_name = "rtmps",
1459 .item_name = av_default_item_name,
1460 .option = rtmp_options,
1461 .version = LIBAVUTIL_VERSION_INT,
1464 URLProtocol ff_rtmps_protocol = {
1466 .url_open = rtmp_open,
1467 .url_read = rtmp_read,
1468 .url_write = rtmp_write,
1469 .url_close = rtmp_close,
1470 .priv_data_size = sizeof(RTMPContext),
1471 .flags = URL_PROTOCOL_FLAG_NETWORK,
1472 .priv_data_class = &rtmps_class,
1475 static const AVClass rtmpt_class = {
1476 .class_name = "rtmpt",
1477 .item_name = av_default_item_name,
1478 .option = rtmp_options,
1479 .version = LIBAVUTIL_VERSION_INT,
1482 URLProtocol ff_rtmpt_protocol = {
1484 .url_open = rtmp_open,
1485 .url_read = rtmp_read,
1486 .url_write = rtmp_write,
1487 .url_close = rtmp_close,
1488 .priv_data_size = sizeof(RTMPContext),
1489 .flags = URL_PROTOCOL_FLAG_NETWORK,
1490 .priv_data_class = &rtmpt_class,
1493 static const AVClass rtmpts_class = {
1494 .class_name = "rtmpts",
1495 .item_name = av_default_item_name,
1496 .option = rtmp_options,
1497 .version = LIBAVUTIL_VERSION_INT,
1500 URLProtocol ff_rtmpts_protocol = {
1502 .url_open = rtmp_open,
1503 .url_read = rtmp_read,
1504 .url_write = rtmp_write,
1505 .url_close = rtmp_close,
1506 .priv_data_size = sizeof(RTMPContext),
1507 .flags = URL_PROTOCOL_FLAG_NETWORK,
1508 .priv_data_class = &rtmpts_class,