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 ClientState state; ///< current state
74 int main_channel_id; ///< an additional channel ID which is used for some invocations
75 uint8_t* flv_data; ///< buffer with data for demuxer
76 int flv_size; ///< current buffer size
77 int flv_off; ///< number of bytes read from current buffer
78 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
79 uint32_t client_report_size; ///< number of bytes after which client should report to server
80 uint32_t bytes_read; ///< number of bytes read from server
81 uint32_t last_bytes_read; ///< number of bytes read last reported to server
82 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
83 uint8_t flv_header[11]; ///< partial incoming flv packet header
84 int flv_header_bytes; ///< number of initialized bytes in flv_header
85 int nb_invokes; ///< keeps track of invoke messages
86 int create_stream_invoke; ///< invoke id for the create stream command
87 char* tcurl; ///< url of the target stream
88 char* flashver; ///< version of the flash plugin
89 char* swfurl; ///< url of the swf player
92 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
93 /** Client key used for digest signing */
94 static const uint8_t rtmp_player_key[] = {
95 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
96 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
98 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
99 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
100 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
103 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
104 /** Key used for RTMP server digest signing */
105 static const uint8_t rtmp_server_key[] = {
106 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
107 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
108 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
110 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
111 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
112 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
116 * Generate 'connect' call and send it to the server.
118 static void gen_connect(URLContext *s, RTMPContext *rt)
123 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
126 ff_amf_write_string(&p, "connect");
127 ff_amf_write_number(&p, ++rt->nb_invokes);
128 ff_amf_write_object_start(&p);
129 ff_amf_write_field_name(&p, "app");
130 ff_amf_write_string(&p, rt->app);
133 ff_amf_write_field_name(&p, "type");
134 ff_amf_write_string(&p, "nonprivate");
136 ff_amf_write_field_name(&p, "flashVer");
137 ff_amf_write_string(&p, rt->flashver);
140 ff_amf_write_field_name(&p, "swfUrl");
141 ff_amf_write_string(&p, rt->swfurl);
144 ff_amf_write_field_name(&p, "tcUrl");
145 ff_amf_write_string(&p, rt->tcurl);
147 ff_amf_write_field_name(&p, "fpad");
148 ff_amf_write_bool(&p, 0);
149 ff_amf_write_field_name(&p, "capabilities");
150 ff_amf_write_number(&p, 15.0);
152 /* Tell the server we support all the audio codecs except
153 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
154 * which are unused in the RTMP protocol implementation. */
155 ff_amf_write_field_name(&p, "audioCodecs");
156 ff_amf_write_number(&p, 4071.0);
157 ff_amf_write_field_name(&p, "videoCodecs");
158 ff_amf_write_number(&p, 252.0);
159 ff_amf_write_field_name(&p, "videoFunction");
160 ff_amf_write_number(&p, 1.0);
162 ff_amf_write_object_end(&p);
164 pkt.data_size = p - pkt.data;
166 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
167 ff_rtmp_packet_destroy(&pkt);
171 * Generate 'releaseStream' call and send it to the server. It should make
172 * the server release some channel for media streams.
174 static void gen_release_stream(URLContext *s, RTMPContext *rt)
179 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
180 29 + strlen(rt->playpath));
182 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
184 ff_amf_write_string(&p, "releaseStream");
185 ff_amf_write_number(&p, ++rt->nb_invokes);
186 ff_amf_write_null(&p);
187 ff_amf_write_string(&p, rt->playpath);
189 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
190 ff_rtmp_packet_destroy(&pkt);
194 * Generate 'FCPublish' call and send it to the server. It should make
195 * the server preapare for receiving media streams.
197 static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
202 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
203 25 + strlen(rt->playpath));
205 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
207 ff_amf_write_string(&p, "FCPublish");
208 ff_amf_write_number(&p, ++rt->nb_invokes);
209 ff_amf_write_null(&p);
210 ff_amf_write_string(&p, rt->playpath);
212 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
213 ff_rtmp_packet_destroy(&pkt);
217 * Generate 'FCUnpublish' call and send it to the server. It should make
218 * the server destroy stream.
220 static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
225 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
226 27 + strlen(rt->playpath));
228 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
230 ff_amf_write_string(&p, "FCUnpublish");
231 ff_amf_write_number(&p, ++rt->nb_invokes);
232 ff_amf_write_null(&p);
233 ff_amf_write_string(&p, rt->playpath);
235 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
236 ff_rtmp_packet_destroy(&pkt);
240 * Generate 'createStream' call and send it to the server. It should make
241 * the server allocate some channel for media streams.
243 static void gen_create_stream(URLContext *s, RTMPContext *rt)
248 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
249 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 25);
252 ff_amf_write_string(&p, "createStream");
253 ff_amf_write_number(&p, ++rt->nb_invokes);
254 ff_amf_write_null(&p);
255 rt->create_stream_invoke = rt->nb_invokes;
257 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
258 ff_rtmp_packet_destroy(&pkt);
263 * Generate 'deleteStream' call and send it to the server. It should make
264 * the server remove some channel for media streams.
266 static void gen_delete_stream(URLContext *s, RTMPContext *rt)
271 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
272 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 34);
275 ff_amf_write_string(&p, "deleteStream");
276 ff_amf_write_number(&p, ++rt->nb_invokes);
277 ff_amf_write_null(&p);
278 ff_amf_write_number(&p, rt->main_channel_id);
280 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
281 ff_rtmp_packet_destroy(&pkt);
285 * Generate 'play' call and send it to the server, then ping the server
286 * to start actual playing.
288 static void gen_play(URLContext *s, RTMPContext *rt)
293 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
294 ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0,
295 29 + strlen(rt->playpath));
296 pkt.extra = rt->main_channel_id;
299 ff_amf_write_string(&p, "play");
300 ff_amf_write_number(&p, ++rt->nb_invokes);
301 ff_amf_write_null(&p);
302 ff_amf_write_string(&p, rt->playpath);
303 ff_amf_write_number(&p, rt->live);
305 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
306 ff_rtmp_packet_destroy(&pkt);
308 // set client buffer time disguised in ping packet
309 ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, 1, 10);
312 bytestream_put_be16(&p, 3);
313 bytestream_put_be32(&p, 1);
314 bytestream_put_be32(&p, 256); //TODO: what is a good value here?
316 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
317 ff_rtmp_packet_destroy(&pkt);
321 * Generate 'publish' call and send it to the server.
323 static void gen_publish(URLContext *s, RTMPContext *rt)
328 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
329 ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE, 0,
330 30 + strlen(rt->playpath));
331 pkt.extra = rt->main_channel_id;
334 ff_amf_write_string(&p, "publish");
335 ff_amf_write_number(&p, ++rt->nb_invokes);
336 ff_amf_write_null(&p);
337 ff_amf_write_string(&p, rt->playpath);
338 ff_amf_write_string(&p, "live");
340 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
341 ff_rtmp_packet_destroy(&pkt);
345 * Generate ping reply and send it to the server.
347 static void gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
352 ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, ppkt->timestamp + 1, 6);
354 bytestream_put_be16(&p, 7);
355 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
356 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
357 ff_rtmp_packet_destroy(&pkt);
361 * Generate server bandwidth message and send it to the server.
363 static void gen_server_bw(URLContext *s, RTMPContext *rt)
368 ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW, 0, 4);
370 bytestream_put_be32(&p, 2500000);
371 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
372 ff_rtmp_packet_destroy(&pkt);
376 * Generate check bandwidth message and send it to the server.
378 static void gen_check_bw(URLContext *s, RTMPContext *rt)
383 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 21);
386 ff_amf_write_string(&p, "_checkbw");
387 ff_amf_write_number(&p, ++rt->nb_invokes);
388 ff_amf_write_null(&p);
390 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
391 ff_rtmp_packet_destroy(&pkt);
395 * Generate report on bytes read so far and send it to the server.
397 static void gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
402 ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ, ts, 4);
404 bytestream_put_be32(&p, rt->bytes_read);
405 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
406 ff_rtmp_packet_destroy(&pkt);
409 //TODO: Move HMAC code somewhere. Eventually.
410 #define HMAC_IPAD_VAL 0x36
411 #define HMAC_OPAD_VAL 0x5C
414 * Calculate HMAC-SHA2 digest for RTMP handshake packets.
416 * @param src input buffer
417 * @param len input buffer length (should be 1536)
418 * @param gap offset in buffer where 32 bytes should not be taken into account
419 * when calculating digest (since it will be used to store that digest)
420 * @param key digest key
421 * @param keylen digest key length
422 * @param dst buffer where calculated digest will be stored (32 bytes)
424 static void rtmp_calc_digest(const uint8_t *src, int len, int gap,
425 const uint8_t *key, int keylen, uint8_t *dst)
428 uint8_t hmac_buf[64+32] = {0};
431 sha = av_mallocz(av_sha_size);
434 memcpy(hmac_buf, key, keylen);
436 av_sha_init(sha, 256);
437 av_sha_update(sha,key, keylen);
438 av_sha_final(sha, hmac_buf);
440 for (i = 0; i < 64; i++)
441 hmac_buf[i] ^= HMAC_IPAD_VAL;
443 av_sha_init(sha, 256);
444 av_sha_update(sha, hmac_buf, 64);
446 av_sha_update(sha, src, len);
447 } else { //skip 32 bytes used for storing digest
448 av_sha_update(sha, src, gap);
449 av_sha_update(sha, src + gap + 32, len - gap - 32);
451 av_sha_final(sha, hmac_buf + 64);
453 for (i = 0; i < 64; i++)
454 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
455 av_sha_init(sha, 256);
456 av_sha_update(sha, hmac_buf, 64+32);
457 av_sha_final(sha, dst);
463 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
464 * will be stored) into that packet.
466 * @param buf handshake data (1536 bytes)
467 * @return offset to the digest inside input data
469 static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
471 int i, digest_pos = 0;
473 for (i = 8; i < 12; i++)
474 digest_pos += buf[i];
475 digest_pos = (digest_pos % 728) + 12;
477 rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
478 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
484 * Verify that the received server response has the expected digest value.
486 * @param buf handshake data received from the server (1536 bytes)
487 * @param off position to search digest offset from
488 * @return 0 if digest is valid, digest position otherwise
490 static int rtmp_validate_digest(uint8_t *buf, int off)
492 int i, digest_pos = 0;
495 for (i = 0; i < 4; i++)
496 digest_pos += buf[i + off];
497 digest_pos = (digest_pos % 728) + off + 4;
499 rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
500 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
502 if (!memcmp(digest, buf + digest_pos, 32))
508 * Perform handshake with the server by means of exchanging pseudorandom data
509 * signed with HMAC-SHA2 digest.
511 * @return 0 if handshake succeeds, negative value otherwise
513 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
516 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
517 3, // unencrypted data
518 0, 0, 0, 0, // client uptime
524 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
525 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
527 int server_pos, client_pos;
530 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
532 av_lfg_init(&rnd, 0xDEADC0DE);
533 // generate handshake packet - 1536 bytes of pseudorandom data
534 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
535 tosend[i] = av_lfg_get(&rnd) >> 24;
536 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1);
538 ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1);
539 i = ffurl_read_complete(rt->stream, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1);
540 if (i != RTMP_HANDSHAKE_PACKET_SIZE + 1) {
541 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
544 i = ffurl_read_complete(rt->stream, clientdata, RTMP_HANDSHAKE_PACKET_SIZE);
545 if (i != RTMP_HANDSHAKE_PACKET_SIZE) {
546 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
550 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
551 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
553 if (rt->is_input && serverdata[5] >= 3) {
554 server_pos = rtmp_validate_digest(serverdata + 1, 772);
556 server_pos = rtmp_validate_digest(serverdata + 1, 8);
558 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
563 rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
564 rtmp_server_key, sizeof(rtmp_server_key),
566 rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE-32, 0,
569 if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
570 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
574 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
575 tosend[i] = av_lfg_get(&rnd) >> 24;
576 rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
577 rtmp_player_key, sizeof(rtmp_player_key),
579 rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
581 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
583 // write reply back to the server
584 ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE);
586 ffurl_write(rt->stream, serverdata+1, RTMP_HANDSHAKE_PACKET_SIZE);
593 * Parse received packet and possibly perform some action depending on
594 * the packet contents.
595 * @return 0 for no errors, negative values for serious errors which prevent
596 * further communications, positive values for uncritical errors
598 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
601 const uint8_t *data_end = pkt->data + pkt->data_size;
604 ff_rtmp_packet_dump(s, pkt);
608 case RTMP_PT_CHUNK_SIZE:
609 if (pkt->data_size != 4) {
610 av_log(s, AV_LOG_ERROR,
611 "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
615 ff_rtmp_packet_write(rt->stream, pkt, rt->chunk_size, rt->prev_pkt[1]);
616 rt->chunk_size = AV_RB32(pkt->data);
617 if (rt->chunk_size <= 0) {
618 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
621 av_log(s, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
624 t = AV_RB16(pkt->data);
626 gen_pong(s, rt, pkt);
628 case RTMP_PT_CLIENT_BW:
629 if (pkt->data_size < 4) {
630 av_log(s, AV_LOG_ERROR,
631 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
635 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
636 rt->client_report_size = AV_RB32(pkt->data) >> 1;
639 //TODO: check for the messages sent for wrong state?
640 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
643 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
644 "description", tmpstr, sizeof(tmpstr)))
645 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
647 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
649 case STATE_HANDSHAKED:
651 gen_release_stream(s, rt);
652 gen_fcpublish_stream(s, rt);
653 rt->state = STATE_RELEASING;
655 gen_server_bw(s, rt);
656 rt->state = STATE_CONNECTING;
658 gen_create_stream(s, rt);
660 case STATE_FCPUBLISH:
661 rt->state = STATE_CONNECTING;
663 case STATE_RELEASING:
664 rt->state = STATE_FCPUBLISH;
665 /* hack for Wowza Media Server, it does not send result for
666 * releaseStream and FCPublish calls */
667 if (!pkt->data[10]) {
668 int pkt_id = av_int2double(AV_RB64(pkt->data + 11));
669 if (pkt_id == rt->create_stream_invoke)
670 rt->state = STATE_CONNECTING;
672 if (rt->state != STATE_CONNECTING)
674 case STATE_CONNECTING:
675 //extract a number from the result
676 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
677 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
679 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
686 rt->state = STATE_READY;
689 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
690 const uint8_t* ptr = pkt->data + 11;
693 for (i = 0; i < 2; i++) {
694 t = ff_amf_tag_size(ptr, data_end);
699 t = ff_amf_get_field_value(ptr, data_end,
700 "level", tmpstr, sizeof(tmpstr));
701 if (!t && !strcmp(tmpstr, "error")) {
702 if (!ff_amf_get_field_value(ptr, data_end,
703 "description", tmpstr, sizeof(tmpstr)))
704 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
707 t = ff_amf_get_field_value(ptr, data_end,
708 "code", tmpstr, sizeof(tmpstr));
709 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
710 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
711 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
712 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
713 } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
722 * Interact with the server by receiving and sending RTMP packets until
723 * there is some significant data (media data or expected status notification).
725 * @param s reading context
726 * @param for_header non-zero value tells function to work until it
727 * gets notification from the server that playing has been started,
728 * otherwise function will work until some media data is received (or
730 * @return 0 for successful operation, negative value in case of error
732 static int get_packet(URLContext *s, int for_header)
734 RTMPContext *rt = s->priv_data;
739 uint32_t ts, cts, pts=0;
741 if (rt->state == STATE_STOPPED)
745 RTMPPacket rpkt = { 0 };
746 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
747 rt->chunk_size, rt->prev_pkt[0])) <= 0) {
749 return AVERROR(EAGAIN);
754 rt->bytes_read += ret;
755 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
756 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
757 gen_bytes_read(s, rt, rpkt.timestamp + 1);
758 rt->last_bytes_read = rt->bytes_read;
761 ret = rtmp_parse_result(s, rt, &rpkt);
762 if (ret < 0) {//serious error in current packet
763 ff_rtmp_packet_destroy(&rpkt);
766 if (rt->state == STATE_STOPPED) {
767 ff_rtmp_packet_destroy(&rpkt);
770 if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
771 ff_rtmp_packet_destroy(&rpkt);
774 if (!rpkt.data_size || !rt->is_input) {
775 ff_rtmp_packet_destroy(&rpkt);
778 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
779 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
782 // generate packet header and put data into buffer for FLV demuxer
784 rt->flv_size = rpkt.data_size + 15;
785 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
786 bytestream_put_byte(&p, rpkt.type);
787 bytestream_put_be24(&p, rpkt.data_size);
788 bytestream_put_be24(&p, ts);
789 bytestream_put_byte(&p, ts >> 24);
790 bytestream_put_be24(&p, 0);
791 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
792 bytestream_put_be32(&p, 0);
793 ff_rtmp_packet_destroy(&rpkt);
795 } else if (rpkt.type == RTMP_PT_METADATA) {
796 // we got raw FLV data, make it available for FLV demuxer
798 rt->flv_size = rpkt.data_size;
799 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
800 /* rewrite timestamps */
803 while (next - rpkt.data < rpkt.data_size - 11) {
805 data_size = bytestream_get_be24(&next);
807 cts = bytestream_get_be24(&next);
808 cts |= bytestream_get_byte(&next) << 24;
813 bytestream_put_be24(&p, ts);
814 bytestream_put_byte(&p, ts >> 24);
815 next += data_size + 3 + 4;
817 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
818 ff_rtmp_packet_destroy(&rpkt);
821 ff_rtmp_packet_destroy(&rpkt);
825 static int rtmp_close(URLContext *h)
827 RTMPContext *rt = h->priv_data;
831 if (rt->out_pkt.data_size)
832 ff_rtmp_packet_destroy(&rt->out_pkt);
833 if (rt->state > STATE_FCPUBLISH)
834 gen_fcunpublish_stream(h, rt);
836 if (rt->state > STATE_HANDSHAKED)
837 gen_delete_stream(h, rt);
839 av_freep(&rt->flv_data);
840 ffurl_close(rt->stream);
845 * Open RTMP connection and verify that the stream can be played.
847 * URL syntax: rtmp://server[:port][/app][/playpath]
848 * where 'app' is first one or two directories in the path
849 * (e.g. /ondemand/, /flash/live/, etc.)
850 * and 'playpath' is a file name (the rest of the path,
851 * may be prefixed with "mp4:")
853 static int rtmp_open(URLContext *s, const char *uri, int flags)
855 RTMPContext *rt = s->priv_data;
856 char proto[8], hostname[256], path[1024], *fname;
862 rt->is_input = !(flags & AVIO_FLAG_WRITE);
864 av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
865 path, sizeof(path), s->filename);
868 port = RTMP_DEFAULT_PORT;
869 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
871 if (ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
872 &s->interrupt_callback, NULL) < 0) {
873 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
877 rt->state = STATE_START;
878 if (rtmp_handshake(s, rt))
881 rt->chunk_size = 128;
882 rt->state = STATE_HANDSHAKED;
884 // Keep the application name when it has been defined by the user.
887 rt->app = av_malloc(APP_MAX_LENGTH);
890 return AVERROR(ENOMEM);
893 //extract "app" part from path
894 if (!strncmp(path, "/ondemand/", 10)) {
896 memcpy(rt->app, "ondemand", 9);
898 char *p = strchr(path + 1, '/');
903 char *c = strchr(p + 1, ':');
904 fname = strchr(p + 1, '/');
905 if (!fname || c < fname) {
907 av_strlcpy(rt->app, path + 1, p - path);
910 av_strlcpy(rt->app, path + 1, fname - path - 1);
916 // The name of application has been defined by the user, override it.
922 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
925 return AVERROR(ENOMEM);
928 if (!strchr(fname, ':') &&
929 (!strcmp(fname + strlen(fname) - 4, ".f4v") ||
930 !strcmp(fname + strlen(fname) - 4, ".mp4"))) {
931 memcpy(rt->playpath, "mp4:", 5);
935 strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5);
939 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
940 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
941 port, "/%s", rt->app);
945 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
947 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
948 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
949 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
951 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
952 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
956 rt->client_report_size = 1048576;
958 rt->last_bytes_read = 0;
960 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
961 proto, path, rt->app, rt->playpath);
965 ret = get_packet(s, 1);
966 } while (ret == EAGAIN);
971 // generate FLV header for demuxer
973 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
975 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
983 s->max_packet_size = rt->stream->max_packet_size;
992 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
994 RTMPContext *rt = s->priv_data;
995 int orig_size = size;
999 int data_left = rt->flv_size - rt->flv_off;
1001 if (data_left >= size) {
1002 memcpy(buf, rt->flv_data + rt->flv_off, size);
1003 rt->flv_off += size;
1006 if (data_left > 0) {
1007 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
1010 rt->flv_off = rt->flv_size;
1013 if ((ret = get_packet(s, 0)) < 0)
1019 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
1021 RTMPContext *rt = s->priv_data;
1022 int size_temp = size;
1023 int pktsize, pkttype;
1025 const uint8_t *buf_temp = buf;
1028 if (rt->skip_bytes) {
1029 int skip = FFMIN(rt->skip_bytes, size_temp);
1032 rt->skip_bytes -= skip;
1036 if (rt->flv_header_bytes < 11) {
1037 const uint8_t *header = rt->flv_header;
1038 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
1039 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
1040 rt->flv_header_bytes += copy;
1042 if (rt->flv_header_bytes < 11)
1045 pkttype = bytestream_get_byte(&header);
1046 pktsize = bytestream_get_be24(&header);
1047 ts = bytestream_get_be24(&header);
1048 ts |= bytestream_get_byte(&header) << 24;
1049 bytestream_get_be24(&header);
1050 rt->flv_size = pktsize;
1052 //force 12bytes header
1053 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
1054 pkttype == RTMP_PT_NOTIFY) {
1055 if (pkttype == RTMP_PT_NOTIFY)
1057 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
1060 //this can be a big packet, it's better to send it right here
1061 ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL, pkttype, ts, pktsize);
1062 rt->out_pkt.extra = rt->main_channel_id;
1063 rt->flv_data = rt->out_pkt.data;
1065 if (pkttype == RTMP_PT_NOTIFY)
1066 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
1069 if (rt->flv_size - rt->flv_off > size_temp) {
1070 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
1071 rt->flv_off += size_temp;
1074 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
1075 size_temp -= rt->flv_size - rt->flv_off;
1076 rt->flv_off += rt->flv_size - rt->flv_off;
1079 if (rt->flv_off == rt->flv_size) {
1082 ff_rtmp_packet_write(rt->stream, &rt->out_pkt, rt->chunk_size, rt->prev_pkt[1]);
1083 ff_rtmp_packet_destroy(&rt->out_pkt);
1086 rt->flv_header_bytes = 0;
1088 } while (buf_temp - buf < size);
1092 #define OFFSET(x) offsetof(RTMPContext, x)
1093 #define DEC AV_OPT_FLAG_DECODING_PARAM
1094 #define ENC AV_OPT_FLAG_ENCODING_PARAM
1096 static const AVOption rtmp_options[] = {
1097 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1098 {"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},
1099 {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
1100 {"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
1101 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
1102 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"},
1103 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1104 {"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},
1105 {"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},
1109 static const AVClass rtmp_class = {
1110 .class_name = "rtmp",
1111 .item_name = av_default_item_name,
1112 .option = rtmp_options,
1113 .version = LIBAVUTIL_VERSION_INT,
1116 URLProtocol ff_rtmp_protocol = {
1118 .url_open = rtmp_open,
1119 .url_read = rtmp_read,
1120 .url_write = rtmp_write,
1121 .url_close = rtmp_close,
1122 .priv_data_size = sizeof(RTMPContext),
1123 .flags = URL_PROTOCOL_FLAG_NETWORK,
1124 .priv_data_class= &rtmp_class,