2 * RTMP network protocol
3 * Copyright (c) 2009 Kostya Shishkov
5 * This file is part of Libav.
7 * Libav 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 * Libav 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 Libav; 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
47 /** RTMP protocol handler state */
49 STATE_START, ///< client has not done anything yet
50 STATE_HANDSHAKED, ///< client has performed handshake
51 STATE_RELEASING, ///< client releasing stream before publish it (for output)
52 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
53 STATE_CONNECTING, ///< client connected to server successfully
54 STATE_READY, ///< client has sent all needed commands and waits for server reply
55 STATE_PLAYING, ///< client has started receiving multimedia data from server
56 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
57 STATE_STOPPED, ///< the broadcast has been stopped
60 /** protocol handler context */
61 typedef struct RTMPContext {
63 URLContext* stream; ///< TCP stream used in interactions with RTMP server
64 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
65 int chunk_size; ///< size of the chunks RTMP packets are divided into
66 int is_input; ///< input/output flag
67 char playpath[256]; ///< path to filename to play (with possible "mp4:" prefix)
68 char *app; ///< name of application
69 ClientState state; ///< current state
70 int main_channel_id; ///< an additional channel ID which is used for some invocations
71 uint8_t* flv_data; ///< buffer with data for demuxer
72 int flv_size; ///< current buffer size
73 int flv_off; ///< number of bytes read from current buffer
74 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
75 uint32_t client_report_size; ///< number of bytes after which client should report to server
76 uint32_t bytes_read; ///< number of bytes read from server
77 uint32_t last_bytes_read; ///< number of bytes read last reported to server
78 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
79 uint8_t flv_header[11]; ///< partial incoming flv packet header
80 int flv_header_bytes; ///< number of initialized bytes in flv_header
81 int nb_invokes; ///< keeps track of invoke messages
82 int create_stream_invoke; ///< invoke id for the create stream command
85 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
86 /** Client key used for digest signing */
87 static const uint8_t rtmp_player_key[] = {
88 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
89 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
91 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
92 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
93 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
96 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
97 /** Key used for RTMP server digest signing */
98 static const uint8_t rtmp_server_key[] = {
99 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
100 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
101 'S', 'e', 'r', 'v', '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
109 * Generate 'connect' call and send it to the server.
111 static void gen_connect(URLContext *s, RTMPContext *rt, const char *proto,
112 const char *host, int port)
118 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
121 ff_url_join(tcurl, sizeof(tcurl), proto, NULL, host, port, "/%s", rt->app);
122 ff_amf_write_string(&p, "connect");
123 ff_amf_write_number(&p, ++rt->nb_invokes);
124 ff_amf_write_object_start(&p);
125 ff_amf_write_field_name(&p, "app");
126 ff_amf_write_string(&p, rt->app);
129 snprintf(ver, sizeof(ver), "%s %d,%d,%d,%d", RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1,
130 RTMP_CLIENT_VER2, RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
132 snprintf(ver, sizeof(ver), "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
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, ver);
138 ff_amf_write_field_name(&p, "tcUrl");
139 ff_amf_write_string(&p, tcurl);
141 ff_amf_write_field_name(&p, "fpad");
142 ff_amf_write_bool(&p, 0);
143 ff_amf_write_field_name(&p, "capabilities");
144 ff_amf_write_number(&p, 15.0);
146 /* Tell the server we support all the audio codecs except
147 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
148 * which are unused in the RTMP protocol implementation. */
149 ff_amf_write_field_name(&p, "audioCodecs");
150 ff_amf_write_number(&p, 4071.0);
151 ff_amf_write_field_name(&p, "videoCodecs");
152 ff_amf_write_number(&p, 252.0);
153 ff_amf_write_field_name(&p, "videoFunction");
154 ff_amf_write_number(&p, 1.0);
156 ff_amf_write_object_end(&p);
158 pkt.data_size = p - pkt.data;
160 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
161 ff_rtmp_packet_destroy(&pkt);
165 * Generate 'releaseStream' call and send it to the server. It should make
166 * the server release some channel for media streams.
168 static void gen_release_stream(URLContext *s, RTMPContext *rt)
173 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
174 29 + strlen(rt->playpath));
176 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
178 ff_amf_write_string(&p, "releaseStream");
179 ff_amf_write_number(&p, ++rt->nb_invokes);
180 ff_amf_write_null(&p);
181 ff_amf_write_string(&p, rt->playpath);
183 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
184 ff_rtmp_packet_destroy(&pkt);
188 * Generate 'FCPublish' call and send it to the server. It should make
189 * the server preapare for receiving media streams.
191 static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
196 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
197 25 + strlen(rt->playpath));
199 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
201 ff_amf_write_string(&p, "FCPublish");
202 ff_amf_write_number(&p, ++rt->nb_invokes);
203 ff_amf_write_null(&p);
204 ff_amf_write_string(&p, rt->playpath);
206 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
207 ff_rtmp_packet_destroy(&pkt);
211 * Generate 'FCUnpublish' call and send it to the server. It should make
212 * the server destroy stream.
214 static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
219 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
220 27 + strlen(rt->playpath));
222 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
224 ff_amf_write_string(&p, "FCUnpublish");
225 ff_amf_write_number(&p, ++rt->nb_invokes);
226 ff_amf_write_null(&p);
227 ff_amf_write_string(&p, rt->playpath);
229 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
230 ff_rtmp_packet_destroy(&pkt);
234 * Generate 'createStream' call and send it to the server. It should make
235 * the server allocate some channel for media streams.
237 static void gen_create_stream(URLContext *s, RTMPContext *rt)
242 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
243 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 25);
246 ff_amf_write_string(&p, "createStream");
247 ff_amf_write_number(&p, ++rt->nb_invokes);
248 ff_amf_write_null(&p);
249 rt->create_stream_invoke = rt->nb_invokes;
251 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
252 ff_rtmp_packet_destroy(&pkt);
257 * Generate 'deleteStream' call and send it to the server. It should make
258 * the server remove some channel for media streams.
260 static void gen_delete_stream(URLContext *s, RTMPContext *rt)
265 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
266 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 34);
269 ff_amf_write_string(&p, "deleteStream");
270 ff_amf_write_number(&p, ++rt->nb_invokes);
271 ff_amf_write_null(&p);
272 ff_amf_write_number(&p, rt->main_channel_id);
274 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
275 ff_rtmp_packet_destroy(&pkt);
279 * Generate 'play' call and send it to the server, then ping the server
280 * to start actual playing.
282 static void gen_play(URLContext *s, RTMPContext *rt)
287 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
288 ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0,
289 20 + strlen(rt->playpath));
290 pkt.extra = rt->main_channel_id;
293 ff_amf_write_string(&p, "play");
294 ff_amf_write_number(&p, ++rt->nb_invokes);
295 ff_amf_write_null(&p);
296 ff_amf_write_string(&p, rt->playpath);
298 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
299 ff_rtmp_packet_destroy(&pkt);
301 // set client buffer time disguised in ping packet
302 ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, 1, 10);
305 bytestream_put_be16(&p, 3);
306 bytestream_put_be32(&p, 1);
307 bytestream_put_be32(&p, 256); //TODO: what is a good value here?
309 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
310 ff_rtmp_packet_destroy(&pkt);
314 * Generate 'publish' call and send it to the server.
316 static void gen_publish(URLContext *s, RTMPContext *rt)
321 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
322 ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE, 0,
323 30 + strlen(rt->playpath));
324 pkt.extra = rt->main_channel_id;
327 ff_amf_write_string(&p, "publish");
328 ff_amf_write_number(&p, ++rt->nb_invokes);
329 ff_amf_write_null(&p);
330 ff_amf_write_string(&p, rt->playpath);
331 ff_amf_write_string(&p, "live");
333 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
334 ff_rtmp_packet_destroy(&pkt);
338 * Generate ping reply and send it to the server.
340 static void gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
345 ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, ppkt->timestamp + 1, 6);
347 bytestream_put_be16(&p, 7);
348 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
349 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
350 ff_rtmp_packet_destroy(&pkt);
354 * Generate server bandwidth message and send it to the server.
356 static void gen_server_bw(URLContext *s, RTMPContext *rt)
361 ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW, 0, 4);
363 bytestream_put_be32(&p, 2500000);
364 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
365 ff_rtmp_packet_destroy(&pkt);
369 * Generate report on bytes read so far and send it to the server.
371 static void gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
376 ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ, ts, 4);
378 bytestream_put_be32(&p, rt->bytes_read);
379 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
380 ff_rtmp_packet_destroy(&pkt);
383 //TODO: Move HMAC code somewhere. Eventually.
384 #define HMAC_IPAD_VAL 0x36
385 #define HMAC_OPAD_VAL 0x5C
388 * Calculate HMAC-SHA2 digest for RTMP handshake packets.
390 * @param src input buffer
391 * @param len input buffer length (should be 1536)
392 * @param gap offset in buffer where 32 bytes should not be taken into account
393 * when calculating digest (since it will be used to store that digest)
394 * @param key digest key
395 * @param keylen digest key length
396 * @param dst buffer where calculated digest will be stored (32 bytes)
398 static void rtmp_calc_digest(const uint8_t *src, int len, int gap,
399 const uint8_t *key, int keylen, uint8_t *dst)
402 uint8_t hmac_buf[64+32] = {0};
405 sha = av_mallocz(av_sha_size);
408 memcpy(hmac_buf, key, keylen);
410 av_sha_init(sha, 256);
411 av_sha_update(sha,key, keylen);
412 av_sha_final(sha, hmac_buf);
414 for (i = 0; i < 64; i++)
415 hmac_buf[i] ^= HMAC_IPAD_VAL;
417 av_sha_init(sha, 256);
418 av_sha_update(sha, hmac_buf, 64);
420 av_sha_update(sha, src, len);
421 } else { //skip 32 bytes used for storing digest
422 av_sha_update(sha, src, gap);
423 av_sha_update(sha, src + gap + 32, len - gap - 32);
425 av_sha_final(sha, hmac_buf + 64);
427 for (i = 0; i < 64; i++)
428 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
429 av_sha_init(sha, 256);
430 av_sha_update(sha, hmac_buf, 64+32);
431 av_sha_final(sha, dst);
437 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
438 * will be stored) into that packet.
440 * @param buf handshake data (1536 bytes)
441 * @return offset to the digest inside input data
443 static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
445 int i, digest_pos = 0;
447 for (i = 8; i < 12; i++)
448 digest_pos += buf[i];
449 digest_pos = (digest_pos % 728) + 12;
451 rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
452 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
458 * Verify that the received server response has the expected digest value.
460 * @param buf handshake data received from the server (1536 bytes)
461 * @param off position to search digest offset from
462 * @return 0 if digest is valid, digest position otherwise
464 static int rtmp_validate_digest(uint8_t *buf, int off)
466 int i, digest_pos = 0;
469 for (i = 0; i < 4; i++)
470 digest_pos += buf[i + off];
471 digest_pos = (digest_pos % 728) + off + 4;
473 rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
474 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
476 if (!memcmp(digest, buf + digest_pos, 32))
482 * Perform handshake with the server by means of exchanging pseudorandom data
483 * signed with HMAC-SHA2 digest.
485 * @return 0 if handshake succeeds, negative value otherwise
487 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
490 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
491 3, // unencrypted data
492 0, 0, 0, 0, // client uptime
498 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
499 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
501 int server_pos, client_pos;
504 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
506 av_lfg_init(&rnd, 0xDEADC0DE);
507 // generate handshake packet - 1536 bytes of pseudorandom data
508 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
509 tosend[i] = av_lfg_get(&rnd) >> 24;
510 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1);
512 ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1);
513 i = ffurl_read_complete(rt->stream, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1);
514 if (i != RTMP_HANDSHAKE_PACKET_SIZE + 1) {
515 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
518 i = ffurl_read_complete(rt->stream, clientdata, RTMP_HANDSHAKE_PACKET_SIZE);
519 if (i != RTMP_HANDSHAKE_PACKET_SIZE) {
520 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
524 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
525 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
527 if (rt->is_input && serverdata[5] >= 3) {
528 server_pos = rtmp_validate_digest(serverdata + 1, 772);
530 server_pos = rtmp_validate_digest(serverdata + 1, 8);
532 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
537 rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
538 rtmp_server_key, sizeof(rtmp_server_key),
540 rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE-32, 0,
543 if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
544 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
548 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
549 tosend[i] = av_lfg_get(&rnd) >> 24;
550 rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
551 rtmp_player_key, sizeof(rtmp_player_key),
553 rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
555 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
557 // write reply back to the server
558 ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE);
560 ffurl_write(rt->stream, serverdata+1, RTMP_HANDSHAKE_PACKET_SIZE);
567 * Parse received packet and possibly perform some action depending on
568 * the packet contents.
569 * @return 0 for no errors, negative values for serious errors which prevent
570 * further communications, positive values for uncritical errors
572 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
575 const uint8_t *data_end = pkt->data + pkt->data_size;
578 ff_rtmp_packet_dump(s, pkt);
582 case RTMP_PT_CHUNK_SIZE:
583 if (pkt->data_size != 4) {
584 av_log(s, AV_LOG_ERROR,
585 "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
589 ff_rtmp_packet_write(rt->stream, pkt, rt->chunk_size, rt->prev_pkt[1]);
590 rt->chunk_size = AV_RB32(pkt->data);
591 if (rt->chunk_size <= 0) {
592 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
595 av_log(s, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
598 t = AV_RB16(pkt->data);
600 gen_pong(s, rt, pkt);
602 case RTMP_PT_CLIENT_BW:
603 if (pkt->data_size < 4) {
604 av_log(s, AV_LOG_ERROR,
605 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
609 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
610 rt->client_report_size = AV_RB32(pkt->data) >> 1;
613 //TODO: check for the messages sent for wrong state?
614 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
617 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
618 "description", tmpstr, sizeof(tmpstr)))
619 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
621 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
623 case STATE_HANDSHAKED:
625 gen_release_stream(s, rt);
626 gen_fcpublish_stream(s, rt);
627 rt->state = STATE_RELEASING;
629 gen_server_bw(s, rt);
630 rt->state = STATE_CONNECTING;
632 gen_create_stream(s, rt);
634 case STATE_FCPUBLISH:
635 rt->state = STATE_CONNECTING;
637 case STATE_RELEASING:
638 rt->state = STATE_FCPUBLISH;
639 /* hack for Wowza Media Server, it does not send result for
640 * releaseStream and FCPublish calls */
641 if (!pkt->data[10]) {
642 int pkt_id = av_int2double(AV_RB64(pkt->data + 11));
643 if (pkt_id == rt->create_stream_invoke)
644 rt->state = STATE_CONNECTING;
646 if (rt->state != STATE_CONNECTING)
648 case STATE_CONNECTING:
649 //extract a number from the result
650 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
651 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
653 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
660 rt->state = STATE_READY;
663 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
664 const uint8_t* ptr = pkt->data + 11;
667 for (i = 0; i < 2; i++) {
668 t = ff_amf_tag_size(ptr, data_end);
673 t = ff_amf_get_field_value(ptr, data_end,
674 "level", tmpstr, sizeof(tmpstr));
675 if (!t && !strcmp(tmpstr, "error")) {
676 if (!ff_amf_get_field_value(ptr, data_end,
677 "description", tmpstr, sizeof(tmpstr)))
678 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
681 t = ff_amf_get_field_value(ptr, data_end,
682 "code", tmpstr, sizeof(tmpstr));
683 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
684 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
685 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
686 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
694 * Interact with the server by receiving and sending RTMP packets until
695 * there is some significant data (media data or expected status notification).
697 * @param s reading context
698 * @param for_header non-zero value tells function to work until it
699 * gets notification from the server that playing has been started,
700 * otherwise function will work until some media data is received (or
702 * @return 0 for successful operation, negative value in case of error
704 static int get_packet(URLContext *s, int for_header)
706 RTMPContext *rt = s->priv_data;
711 uint32_t ts, cts, pts=0;
713 if (rt->state == STATE_STOPPED)
717 RTMPPacket rpkt = { 0 };
718 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
719 rt->chunk_size, rt->prev_pkt[0])) <= 0) {
721 return AVERROR(EAGAIN);
726 rt->bytes_read += ret;
727 if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
728 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
729 gen_bytes_read(s, rt, rpkt.timestamp + 1);
730 rt->last_bytes_read = rt->bytes_read;
733 ret = rtmp_parse_result(s, rt, &rpkt);
734 if (ret < 0) {//serious error in current packet
735 ff_rtmp_packet_destroy(&rpkt);
738 if (rt->state == STATE_STOPPED) {
739 ff_rtmp_packet_destroy(&rpkt);
742 if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
743 ff_rtmp_packet_destroy(&rpkt);
746 if (!rpkt.data_size || !rt->is_input) {
747 ff_rtmp_packet_destroy(&rpkt);
750 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
751 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
754 // generate packet header and put data into buffer for FLV demuxer
756 rt->flv_size = rpkt.data_size + 15;
757 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
758 bytestream_put_byte(&p, rpkt.type);
759 bytestream_put_be24(&p, rpkt.data_size);
760 bytestream_put_be24(&p, ts);
761 bytestream_put_byte(&p, ts >> 24);
762 bytestream_put_be24(&p, 0);
763 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
764 bytestream_put_be32(&p, 0);
765 ff_rtmp_packet_destroy(&rpkt);
767 } else if (rpkt.type == RTMP_PT_METADATA) {
768 // we got raw FLV data, make it available for FLV demuxer
770 rt->flv_size = rpkt.data_size;
771 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
772 /* rewrite timestamps */
775 while (next - rpkt.data < rpkt.data_size - 11) {
777 data_size = bytestream_get_be24(&next);
779 cts = bytestream_get_be24(&next);
780 cts |= bytestream_get_byte(&next) << 24;
785 bytestream_put_be24(&p, ts);
786 bytestream_put_byte(&p, ts >> 24);
787 next += data_size + 3 + 4;
789 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
790 ff_rtmp_packet_destroy(&rpkt);
793 ff_rtmp_packet_destroy(&rpkt);
797 static int rtmp_close(URLContext *h)
799 RTMPContext *rt = h->priv_data;
803 if (rt->out_pkt.data_size)
804 ff_rtmp_packet_destroy(&rt->out_pkt);
805 if (rt->state > STATE_FCPUBLISH)
806 gen_fcunpublish_stream(h, rt);
808 if (rt->state > STATE_HANDSHAKED)
809 gen_delete_stream(h, rt);
811 av_freep(&rt->flv_data);
812 ffurl_close(rt->stream);
817 * Open RTMP connection and verify that the stream can be played.
819 * URL syntax: rtmp://server[:port][/app][/playpath]
820 * where 'app' is first one or two directories in the path
821 * (e.g. /ondemand/, /flash/live/, etc.)
822 * and 'playpath' is a file name (the rest of the path,
823 * may be prefixed with "mp4:")
825 static int rtmp_open(URLContext *s, const char *uri, int flags)
827 RTMPContext *rt = s->priv_data;
828 char proto[8], hostname[256], path[1024], *fname;
834 rt->is_input = !(flags & AVIO_FLAG_WRITE);
836 av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
837 path, sizeof(path), s->filename);
840 port = RTMP_DEFAULT_PORT;
841 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
843 if (ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
844 &s->interrupt_callback, NULL) < 0) {
845 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
849 rt->state = STATE_START;
850 if (rtmp_handshake(s, rt))
853 rt->chunk_size = 128;
854 rt->state = STATE_HANDSHAKED;
856 // Keep the application name when it has been defined by the user.
859 rt->app = av_malloc(APP_MAX_LENGTH);
862 return AVERROR(ENOMEM);
865 //extract "app" part from path
866 if (!strncmp(path, "/ondemand/", 10)) {
868 memcpy(rt->app, "ondemand", 9);
870 char *p = strchr(path + 1, '/');
875 char *c = strchr(p + 1, ':');
876 fname = strchr(p + 1, '/');
877 if (!fname || c < fname) {
879 av_strlcpy(rt->app, path + 1, p - path);
882 av_strlcpy(rt->app, path + 1, fname - path - 1);
888 // The name of application has been defined by the user, override it.
893 if (!strchr(fname, ':') &&
894 (!strcmp(fname + strlen(fname) - 4, ".f4v") ||
895 !strcmp(fname + strlen(fname) - 4, ".mp4"))) {
896 memcpy(rt->playpath, "mp4:", 5);
900 strncat(rt->playpath, fname, sizeof(rt->playpath) - 5);
902 rt->client_report_size = 1048576;
904 rt->last_bytes_read = 0;
906 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
907 proto, path, rt->app, rt->playpath);
908 gen_connect(s, rt, proto, hostname, port);
911 ret = get_packet(s, 1);
912 } while (ret == EAGAIN);
917 // generate FLV header for demuxer
919 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
921 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
929 s->max_packet_size = rt->stream->max_packet_size;
938 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
940 RTMPContext *rt = s->priv_data;
941 int orig_size = size;
945 int data_left = rt->flv_size - rt->flv_off;
947 if (data_left >= size) {
948 memcpy(buf, rt->flv_data + rt->flv_off, size);
953 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
956 rt->flv_off = rt->flv_size;
959 if ((ret = get_packet(s, 0)) < 0)
965 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
967 RTMPContext *rt = s->priv_data;
968 int size_temp = size;
969 int pktsize, pkttype;
971 const uint8_t *buf_temp = buf;
974 if (rt->skip_bytes) {
975 int skip = FFMIN(rt->skip_bytes, size_temp);
978 rt->skip_bytes -= skip;
982 if (rt->flv_header_bytes < 11) {
983 const uint8_t *header = rt->flv_header;
984 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
985 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
986 rt->flv_header_bytes += copy;
988 if (rt->flv_header_bytes < 11)
991 pkttype = bytestream_get_byte(&header);
992 pktsize = bytestream_get_be24(&header);
993 ts = bytestream_get_be24(&header);
994 ts |= bytestream_get_byte(&header) << 24;
995 bytestream_get_be24(&header);
996 rt->flv_size = pktsize;
998 //force 12bytes header
999 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
1000 pkttype == RTMP_PT_NOTIFY) {
1001 if (pkttype == RTMP_PT_NOTIFY)
1003 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
1006 //this can be a big packet, it's better to send it right here
1007 ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL, pkttype, ts, pktsize);
1008 rt->out_pkt.extra = rt->main_channel_id;
1009 rt->flv_data = rt->out_pkt.data;
1011 if (pkttype == RTMP_PT_NOTIFY)
1012 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
1015 if (rt->flv_size - rt->flv_off > size_temp) {
1016 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
1017 rt->flv_off += size_temp;
1020 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
1021 size_temp -= rt->flv_size - rt->flv_off;
1022 rt->flv_off += rt->flv_size - rt->flv_off;
1025 if (rt->flv_off == rt->flv_size) {
1028 ff_rtmp_packet_write(rt->stream, &rt->out_pkt, rt->chunk_size, rt->prev_pkt[1]);
1029 ff_rtmp_packet_destroy(&rt->out_pkt);
1032 rt->flv_header_bytes = 0;
1034 } while (buf_temp - buf < size);
1038 #define OFFSET(x) offsetof(RTMPContext, x)
1039 #define DEC AV_OPT_FLAG_DECODING_PARAM
1040 #define ENC AV_OPT_FLAG_ENCODING_PARAM
1042 static const AVOption rtmp_options[] = {
1043 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1047 static const AVClass rtmp_class = {
1048 .class_name = "rtmp",
1049 .item_name = av_default_item_name,
1050 .option = rtmp_options,
1051 .version = LIBAVUTIL_VERSION_INT,
1054 URLProtocol ff_rtmp_protocol = {
1056 .url_open = rtmp_open,
1057 .url_read = rtmp_read,
1058 .url_write = rtmp_write,
1059 .url_close = rtmp_close,
1060 .priv_data_size = sizeof(RTMPContext),
1061 .flags = URL_PROTOCOL_FLAG_NETWORK,
1062 .priv_data_class= &rtmp_class,