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/random_seed.h"
33 #include "libavutil/sha.h"
41 #include "rtmpcrypt.h"
51 #define APP_MAX_LENGTH 128
52 #define PLAYPATH_MAX_LENGTH 256
53 #define TCURL_MAX_LENGTH 512
54 #define FLASHVER_MAX_LENGTH 64
55 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
57 /** RTMP protocol handler state */
59 STATE_START, ///< client has not done anything yet
60 STATE_HANDSHAKED, ///< client has performed handshake
61 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
62 STATE_PLAYING, ///< client has started receiving multimedia data from server
63 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
64 STATE_RECEIVING, ///< received a publish command (for input)
65 STATE_STOPPED, ///< the broadcast has been stopped
68 typedef struct TrackedMethod {
73 /** protocol handler context */
74 typedef struct RTMPContext {
76 URLContext* stream; ///< TCP stream used in interactions with RTMP server
77 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
78 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
79 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
80 int is_input; ///< input/output flag
81 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
82 int live; ///< 0: recorded, -1: live, -2: both
83 char *app; ///< name of application
84 char *conn; ///< append arbitrary AMF data to the Connect message
85 ClientState state; ///< current state
86 int main_channel_id; ///< an additional channel ID which is used for some invocations
87 uint8_t* flv_data; ///< buffer with data for demuxer
88 int flv_size; ///< current buffer size
89 int flv_off; ///< number of bytes read from current buffer
90 int flv_nb_packets; ///< number of flv packets published
91 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
92 uint32_t client_report_size; ///< number of bytes after which client should report to server
93 uint32_t bytes_read; ///< number of bytes read from server
94 uint32_t last_bytes_read; ///< number of bytes read last reported to server
95 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
96 uint8_t flv_header[11]; ///< partial incoming flv packet header
97 int flv_header_bytes; ///< number of initialized bytes in flv_header
98 int nb_invokes; ///< keeps track of invoke messages
99 char* tcurl; ///< url of the target stream
100 char* flashver; ///< version of the flash plugin
101 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
102 int swfhash_len; ///< length of the SHA256 hash
103 int swfsize; ///< size of the decompressed SWF file
104 char* swfurl; ///< url of the swf player
105 char* swfverify; ///< URL to player swf file, compute hash/size automatically
106 char swfverification[42]; ///< hash of the SWF verification
107 char* pageurl; ///< url of the web page
108 char* subscribe; ///< name of live stream to subscribe
109 int server_bw; ///< server bandwidth
110 int client_buffer_time; ///< client buffer time in ms
111 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
112 int encrypted; ///< use an encrypted connection (RTMPE only)
113 TrackedMethod*tracked_methods; ///< tracked methods buffer
114 int nb_tracked_methods; ///< number of tracked methods
115 int tracked_methods_size; ///< size of the tracked methods buffer
116 int listen; ///< listen mode flag
117 int listen_timeout; ///< listen timeout to wait for new connections
118 int nb_streamid; ///< The next stream id to return on createStream calls
121 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
122 /** Client key used for digest signing */
123 static const uint8_t rtmp_player_key[] = {
124 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
125 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
127 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
128 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
129 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
132 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
133 /** Key used for RTMP server digest signing */
134 static const uint8_t rtmp_server_key[] = {
135 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
136 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
137 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
139 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
140 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
141 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
144 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
148 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
149 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
150 ptr = av_realloc(rt->tracked_methods,
151 rt->tracked_methods_size * sizeof(*rt->tracked_methods));
153 return AVERROR(ENOMEM);
154 rt->tracked_methods = ptr;
157 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
158 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
159 return AVERROR(ENOMEM);
160 rt->tracked_methods[rt->nb_tracked_methods].id = id;
161 rt->nb_tracked_methods++;
166 static void del_tracked_method(RTMPContext *rt, int index)
168 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
169 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
170 rt->nb_tracked_methods--;
173 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
174 char **tracked_method)
176 RTMPContext *rt = s->priv_data;
182 bytestream2_init(&gbc, pkt->data + offset, pkt->data_size - offset);
183 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
186 for (i = 0; i < rt->nb_tracked_methods; i++) {
187 if (rt->tracked_methods[i].id != pkt_id)
190 *tracked_method = rt->tracked_methods[i].name;
191 del_tracked_method(rt, i);
198 static void free_tracked_methods(RTMPContext *rt)
202 for (i = 0; i < rt->nb_tracked_methods; i ++)
203 av_free(rt->tracked_methods[i].name);
204 av_free(rt->tracked_methods);
207 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
211 if (pkt->type == RTMP_PT_INVOKE && track) {
217 bytestream2_init(&gbc, pkt->data, pkt->data_size);
218 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
221 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
224 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
228 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
231 ff_rtmp_packet_destroy(pkt);
235 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
240 /* The type must be B for Boolean, N for number, S for string, O for
241 * object, or Z for null. For Booleans the data must be either 0 or 1 for
242 * FALSE or TRUE, respectively. Likewise for Objects the data must be
243 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
244 * may be named, by prefixing the type with 'N' and specifying the name
245 * before the value (ie. NB:myFlag:1). This option may be used multiple times
246 * to construct arbitrary AMF sequences. */
247 if (param[0] && param[1] == ':') {
250 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
253 value = strchr(field, ':');
259 if (!field || !value)
262 ff_amf_write_field_name(p, field);
269 ff_amf_write_bool(p, value[0] != '0');
272 ff_amf_write_string(p, value);
275 ff_amf_write_number(p, strtod(value, NULL));
278 ff_amf_write_null(p);
282 ff_amf_write_object_start(p);
284 ff_amf_write_object_end(p);
294 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
295 return AVERROR(EINVAL);
299 * Generate 'connect' call and send it to the server.
301 static int gen_connect(URLContext *s, RTMPContext *rt)
307 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
313 ff_amf_write_string(&p, "connect");
314 ff_amf_write_number(&p, ++rt->nb_invokes);
315 ff_amf_write_object_start(&p);
316 ff_amf_write_field_name(&p, "app");
317 ff_amf_write_string(&p, rt->app);
320 ff_amf_write_field_name(&p, "type");
321 ff_amf_write_string(&p, "nonprivate");
323 ff_amf_write_field_name(&p, "flashVer");
324 ff_amf_write_string(&p, rt->flashver);
327 ff_amf_write_field_name(&p, "swfUrl");
328 ff_amf_write_string(&p, rt->swfurl);
331 ff_amf_write_field_name(&p, "tcUrl");
332 ff_amf_write_string(&p, rt->tcurl);
334 ff_amf_write_field_name(&p, "fpad");
335 ff_amf_write_bool(&p, 0);
336 ff_amf_write_field_name(&p, "capabilities");
337 ff_amf_write_number(&p, 15.0);
339 /* Tell the server we support all the audio codecs except
340 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
341 * which are unused in the RTMP protocol implementation. */
342 ff_amf_write_field_name(&p, "audioCodecs");
343 ff_amf_write_number(&p, 4071.0);
344 ff_amf_write_field_name(&p, "videoCodecs");
345 ff_amf_write_number(&p, 252.0);
346 ff_amf_write_field_name(&p, "videoFunction");
347 ff_amf_write_number(&p, 1.0);
350 ff_amf_write_field_name(&p, "pageUrl");
351 ff_amf_write_string(&p, rt->pageurl);
354 ff_amf_write_object_end(&p);
357 char *param = rt->conn;
359 // Write arbitrary AMF data to the Connect message.
360 while (param != NULL) {
362 param += strspn(param, " ");
365 sep = strchr(param, ' ');
368 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
369 // Invalid AMF parameter.
370 ff_rtmp_packet_destroy(&pkt);
381 pkt.data_size = p - pkt.data;
383 return rtmp_send_packet(rt, &pkt, 1);
386 static int read_connect(URLContext *s, RTMPContext *rt)
388 RTMPPacket pkt = { 0 };
398 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
399 rt->prev_pkt[1])) < 0)
402 bytestream2_init(&gbc, cp, pkt.data_size);
403 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
404 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
405 ff_rtmp_packet_destroy(&pkt);
406 return AVERROR_INVALIDDATA;
408 if (strcmp(command, "connect")) {
409 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
410 ff_rtmp_packet_destroy(&pkt);
411 return AVERROR_INVALIDDATA;
413 ret = ff_amf_read_number(&gbc, &seqnum);
415 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
416 /* Here one could parse an AMF Object with data as flashVers and others. */
417 ret = ff_amf_get_field_value(gbc.buffer,
418 gbc.buffer + bytestream2_get_bytes_left(&gbc),
419 "app", tmpstr, sizeof(tmpstr));
421 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
422 if (!ret && strcmp(tmpstr, rt->app))
423 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
425 ff_rtmp_packet_destroy(&pkt);
427 // Send Window Acknowledgement Size (as defined in speficication)
428 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
429 RTMP_PT_SERVER_BW, 0, 4)) < 0)
432 bytestream_put_be32(&p, rt->server_bw);
433 pkt.data_size = p - pkt.data;
434 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
436 ff_rtmp_packet_destroy(&pkt);
439 // Send Peer Bandwidth
440 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
441 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
444 bytestream_put_be32(&p, rt->server_bw);
445 bytestream_put_byte(&p, 2); // dynamic
446 pkt.data_size = p - pkt.data;
447 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
449 ff_rtmp_packet_destroy(&pkt);
454 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
455 RTMP_PT_PING, 0, 6)) < 0)
459 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
460 bytestream_put_be32(&p, 0);
461 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
463 ff_rtmp_packet_destroy(&pkt);
468 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
469 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
473 bytestream_put_be32(&p, rt->out_chunk_size);
474 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
476 ff_rtmp_packet_destroy(&pkt);
480 // Send result_ NetConnection.Connect.Success to connect
481 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
483 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
487 ff_amf_write_string(&p, "_result");
488 ff_amf_write_number(&p, seqnum);
490 ff_amf_write_object_start(&p);
491 ff_amf_write_field_name(&p, "fmsVer");
492 ff_amf_write_string(&p, "FMS/3,0,1,123");
493 ff_amf_write_field_name(&p, "capabilities");
494 ff_amf_write_number(&p, 31);
495 ff_amf_write_object_end(&p);
497 ff_amf_write_object_start(&p);
498 ff_amf_write_field_name(&p, "level");
499 ff_amf_write_string(&p, "status");
500 ff_amf_write_field_name(&p, "code");
501 ff_amf_write_string(&p, "NetConnection.Connect.Success");
502 ff_amf_write_field_name(&p, "description");
503 ff_amf_write_string(&p, "Connection succeeded.");
504 ff_amf_write_field_name(&p, "objectEncoding");
505 ff_amf_write_number(&p, 0);
506 ff_amf_write_object_end(&p);
508 pkt.data_size = p - pkt.data;
509 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
511 ff_rtmp_packet_destroy(&pkt);
515 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
516 RTMP_PT_INVOKE, 0, 30)) < 0)
519 ff_amf_write_string(&p, "onBWDone");
520 ff_amf_write_number(&p, 0);
521 ff_amf_write_null(&p);
522 ff_amf_write_number(&p, 8192);
523 pkt.data_size = p - pkt.data;
524 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
526 ff_rtmp_packet_destroy(&pkt);
532 * Generate 'releaseStream' call and send it to the server. It should make
533 * the server release some channel for media streams.
535 static int gen_release_stream(URLContext *s, RTMPContext *rt)
541 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
542 0, 29 + strlen(rt->playpath))) < 0)
545 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
547 ff_amf_write_string(&p, "releaseStream");
548 ff_amf_write_number(&p, ++rt->nb_invokes);
549 ff_amf_write_null(&p);
550 ff_amf_write_string(&p, rt->playpath);
552 return rtmp_send_packet(rt, &pkt, 1);
556 * Generate 'FCPublish' call and send it to the server. It should make
557 * the server preapare for receiving media streams.
559 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
565 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
566 0, 25 + strlen(rt->playpath))) < 0)
569 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
571 ff_amf_write_string(&p, "FCPublish");
572 ff_amf_write_number(&p, ++rt->nb_invokes);
573 ff_amf_write_null(&p);
574 ff_amf_write_string(&p, rt->playpath);
576 return rtmp_send_packet(rt, &pkt, 1);
580 * Generate 'FCUnpublish' call and send it to the server. It should make
581 * the server destroy stream.
583 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
589 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
590 0, 27 + strlen(rt->playpath))) < 0)
593 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
595 ff_amf_write_string(&p, "FCUnpublish");
596 ff_amf_write_number(&p, ++rt->nb_invokes);
597 ff_amf_write_null(&p);
598 ff_amf_write_string(&p, rt->playpath);
600 return rtmp_send_packet(rt, &pkt, 0);
604 * Generate 'createStream' call and send it to the server. It should make
605 * the server allocate some channel for media streams.
607 static int gen_create_stream(URLContext *s, RTMPContext *rt)
613 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
615 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
620 ff_amf_write_string(&p, "createStream");
621 ff_amf_write_number(&p, ++rt->nb_invokes);
622 ff_amf_write_null(&p);
624 return rtmp_send_packet(rt, &pkt, 1);
629 * Generate 'deleteStream' call and send it to the server. It should make
630 * the server remove some channel for media streams.
632 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
638 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
640 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
645 ff_amf_write_string(&p, "deleteStream");
646 ff_amf_write_number(&p, ++rt->nb_invokes);
647 ff_amf_write_null(&p);
648 ff_amf_write_number(&p, rt->main_channel_id);
650 return rtmp_send_packet(rt, &pkt, 0);
654 * Generate client buffer time and send it to the server.
656 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
662 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
667 bytestream_put_be16(&p, 3);
668 bytestream_put_be32(&p, rt->main_channel_id);
669 bytestream_put_be32(&p, rt->client_buffer_time);
671 return rtmp_send_packet(rt, &pkt, 0);
675 * Generate 'play' call and send it to the server, then ping the server
676 * to start actual playing.
678 static int gen_play(URLContext *s, RTMPContext *rt)
684 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
686 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
687 0, 29 + strlen(rt->playpath))) < 0)
690 pkt.extra = rt->main_channel_id;
693 ff_amf_write_string(&p, "play");
694 ff_amf_write_number(&p, ++rt->nb_invokes);
695 ff_amf_write_null(&p);
696 ff_amf_write_string(&p, rt->playpath);
697 ff_amf_write_number(&p, rt->live);
699 return rtmp_send_packet(rt, &pkt, 1);
703 * Generate 'publish' call and send it to the server.
705 static int gen_publish(URLContext *s, RTMPContext *rt)
711 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
713 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
714 0, 30 + strlen(rt->playpath))) < 0)
717 pkt.extra = rt->main_channel_id;
720 ff_amf_write_string(&p, "publish");
721 ff_amf_write_number(&p, ++rt->nb_invokes);
722 ff_amf_write_null(&p);
723 ff_amf_write_string(&p, rt->playpath);
724 ff_amf_write_string(&p, "live");
726 return rtmp_send_packet(rt, &pkt, 1);
730 * Generate ping reply and send it to the server.
732 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
738 if (ppkt->data_size < 6) {
739 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
741 return AVERROR_INVALIDDATA;
744 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
745 ppkt->timestamp + 1, 6)) < 0)
749 bytestream_put_be16(&p, 7);
750 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
752 return rtmp_send_packet(rt, &pkt, 0);
756 * Generate SWF verification message and send it to the server.
758 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
764 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
765 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
770 bytestream_put_be16(&p, 27);
771 memcpy(p, rt->swfverification, 42);
773 return rtmp_send_packet(rt, &pkt, 0);
777 * Generate server bandwidth message and send it to the server.
779 static int gen_server_bw(URLContext *s, RTMPContext *rt)
785 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
790 bytestream_put_be32(&p, rt->server_bw);
792 return rtmp_send_packet(rt, &pkt, 0);
796 * Generate check bandwidth message and send it to the server.
798 static int gen_check_bw(URLContext *s, RTMPContext *rt)
804 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
809 ff_amf_write_string(&p, "_checkbw");
810 ff_amf_write_number(&p, ++rt->nb_invokes);
811 ff_amf_write_null(&p);
813 return rtmp_send_packet(rt, &pkt, 1);
817 * Generate report on bytes read so far and send it to the server.
819 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
825 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
830 bytestream_put_be32(&p, rt->bytes_read);
832 return rtmp_send_packet(rt, &pkt, 0);
835 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
836 const char *subscribe)
842 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
843 0, 27 + strlen(subscribe))) < 0)
847 ff_amf_write_string(&p, "FCSubscribe");
848 ff_amf_write_number(&p, ++rt->nb_invokes);
849 ff_amf_write_null(&p);
850 ff_amf_write_string(&p, subscribe);
852 return rtmp_send_packet(rt, &pkt, 1);
855 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
856 const uint8_t *key, int keylen, uint8_t *dst)
859 uint8_t hmac_buf[64+32] = {0};
862 sha = av_mallocz(av_sha_size);
864 return AVERROR(ENOMEM);
867 memcpy(hmac_buf, key, keylen);
869 av_sha_init(sha, 256);
870 av_sha_update(sha,key, keylen);
871 av_sha_final(sha, hmac_buf);
873 for (i = 0; i < 64; i++)
874 hmac_buf[i] ^= HMAC_IPAD_VAL;
876 av_sha_init(sha, 256);
877 av_sha_update(sha, hmac_buf, 64);
879 av_sha_update(sha, src, len);
880 } else { //skip 32 bytes used for storing digest
881 av_sha_update(sha, src, gap);
882 av_sha_update(sha, src + gap + 32, len - gap - 32);
884 av_sha_final(sha, hmac_buf + 64);
886 for (i = 0; i < 64; i++)
887 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
888 av_sha_init(sha, 256);
889 av_sha_update(sha, hmac_buf, 64+32);
890 av_sha_final(sha, dst);
897 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
900 int i, digest_pos = 0;
902 for (i = 0; i < 4; i++)
903 digest_pos += buf[i + off];
904 digest_pos = digest_pos % mod_val + add_val;
910 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
911 * will be stored) into that packet.
913 * @param buf handshake data (1536 bytes)
914 * @param encrypted use an encrypted connection (RTMPE)
915 * @return offset to the digest inside input data
917 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
922 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
924 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
926 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
927 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
936 * Verify that the received server response has the expected digest value.
938 * @param buf handshake data received from the server (1536 bytes)
939 * @param off position to search digest offset from
940 * @return 0 if digest is valid, digest position otherwise
942 static int rtmp_validate_digest(uint8_t *buf, int off)
947 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
949 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
950 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
955 if (!memcmp(digest, buf + digest_pos, 32))
960 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
966 if (rt->swfhash_len != 32) {
967 av_log(s, AV_LOG_ERROR,
968 "Hash of the decompressed SWF file is not 32 bytes long.\n");
969 return AVERROR(EINVAL);
972 p = &rt->swfverification[0];
973 bytestream_put_byte(&p, 1);
974 bytestream_put_byte(&p, 1);
975 bytestream_put_be32(&p, rt->swfsize);
976 bytestream_put_be32(&p, rt->swfsize);
978 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
985 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
986 uint8_t **out_data, int64_t *out_size)
993 zs.avail_in = in_size;
994 zs.next_in = in_data;
995 ret = inflateInit(&zs);
997 return AVERROR_UNKNOWN;
1000 uint8_t tmp_buf[16384];
1002 zs.avail_out = sizeof(tmp_buf);
1003 zs.next_out = tmp_buf;
1005 ret = inflate(&zs, Z_NO_FLUSH);
1006 if (ret != Z_OK && ret != Z_STREAM_END) {
1007 ret = AVERROR_UNKNOWN;
1011 size = sizeof(tmp_buf) - zs.avail_out;
1012 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1013 ret = AVERROR(ENOMEM);
1018 memcpy(*out_data + *out_size, tmp_buf, size);
1020 } while (zs.avail_out == 0);
1028 static int rtmp_calc_swfhash(URLContext *s)
1030 RTMPContext *rt = s->priv_data;
1031 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1032 int64_t in_size, out_size;
1038 /* Get the SWF player file. */
1039 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1040 &s->interrupt_callback, NULL)) < 0) {
1041 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1045 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1050 if (!(in_data = av_malloc(in_size))) {
1051 ret = AVERROR(ENOMEM);
1055 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1059 ret = AVERROR_INVALIDDATA;
1063 if (!memcmp(in_data, "CWS", 3)) {
1064 /* Decompress the SWF player file using Zlib. */
1065 if (!(out_data = av_malloc(8))) {
1066 ret = AVERROR(ENOMEM);
1069 *in_data = 'F'; // magic stuff
1070 memcpy(out_data, in_data, 8);
1074 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1075 &out_data, &out_size)) < 0)
1078 av_log(s, AV_LOG_ERROR,
1079 "Zlib is required for decompressing the SWF player file.\n");
1080 ret = AVERROR(EINVAL);
1090 /* Compute the SHA256 hash of the SWF player file. */
1091 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1092 "Genuine Adobe Flash Player 001", 30,
1096 /* Set SWFVerification parameters. */
1097 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1098 rt->swfsize = swfsize;
1102 av_freep(&out_data);
1103 ffurl_close(stream);
1108 * Perform handshake with the server by means of exchanging pseudorandom data
1109 * signed with HMAC-SHA2 digest.
1111 * @return 0 if handshake succeeds, negative value otherwise
1113 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1116 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1117 3, // unencrypted data
1118 0, 0, 0, 0, // client uptime
1124 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1125 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1127 int server_pos, client_pos;
1128 uint8_t digest[32], signature[32];
1131 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1133 av_lfg_init(&rnd, 0xDEADC0DE);
1134 // generate handshake packet - 1536 bytes of pseudorandom data
1135 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1136 tosend[i] = av_lfg_get(&rnd) >> 24;
1138 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1139 /* When the client wants to use RTMPE, we have to change the command
1140 * byte to 0x06 which means to use encrypted data and we have to set
1141 * the flash version to at least 9.0.115.0. */
1148 /* Initialize the Diffie-Hellmann context and generate the public key
1149 * to send to the server. */
1150 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1154 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1158 if ((ret = ffurl_write(rt->stream, tosend,
1159 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1160 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1164 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1165 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1166 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1170 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1171 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1172 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1176 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1177 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1178 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1180 if (rt->is_input && serverdata[5] >= 3) {
1181 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1187 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1192 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1193 return AVERROR(EIO);
1197 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1198 * key are the last 32 bytes of the server handshake. */
1200 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1201 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1205 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1206 rtmp_server_key, sizeof(rtmp_server_key),
1211 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1212 0, digest, 32, signature);
1216 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1217 /* Compute the shared secret key sent by the server and initialize
1218 * the RC4 encryption. */
1219 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1220 tosend + 1, type)) < 0)
1223 /* Encrypt the signature received by the server. */
1224 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1227 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1228 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1229 return AVERROR(EIO);
1232 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1233 tosend[i] = av_lfg_get(&rnd) >> 24;
1234 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1235 rtmp_player_key, sizeof(rtmp_player_key),
1240 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1242 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1246 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1247 /* Encrypt the signature to be send to the server. */
1248 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1249 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1253 // write reply back to the server
1254 if ((ret = ffurl_write(rt->stream, tosend,
1255 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1258 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1259 /* Set RC4 keys for encryption and update the keystreams. */
1260 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1264 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1265 /* Compute the shared secret key sent by the server and initialize
1266 * the RC4 encryption. */
1267 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1268 tosend + 1, 1)) < 0)
1271 if (serverdata[0] == 9) {
1272 /* Encrypt the signature received by the server. */
1273 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1278 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1279 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1282 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1283 /* Set RC4 keys for encryption and update the keystreams. */
1284 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1292 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1293 uint32_t *second_int, char *arraydata,
1298 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1299 RTMP_HANDSHAKE_PACKET_SIZE);
1301 return AVERROR(EIO);
1302 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1303 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1304 " not following standard\n", (int)inoutsize);
1305 return AVERROR(EINVAL);
1308 *first_int = AV_RB32(arraydata);
1309 *second_int = AV_RB32(arraydata + 4);
1313 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1314 uint32_t second_int, char *arraydata, int size)
1318 AV_WB32(arraydata, first_int);
1319 AV_WB32(arraydata + 4, first_int);
1320 inoutsize = ffurl_write(rt->stream, arraydata,
1321 RTMP_HANDSHAKE_PACKET_SIZE);
1322 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1323 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1324 return AVERROR(EIO);
1331 * rtmp handshake server side
1333 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1335 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1337 uint32_t hs_my_epoch;
1338 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1339 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1346 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1347 if (inoutsize <= 0) {
1348 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1349 return AVERROR(EIO);
1352 if (buffer[0] != 3) {
1353 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1354 return AVERROR(EIO);
1356 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1357 av_log(s, AV_LOG_ERROR,
1358 "Unable to write answer - RTMP S0\n");
1359 return AVERROR(EIO);
1362 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1363 RTMP_HANDSHAKE_PACKET_SIZE);
1365 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1369 av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1371 /* By now same epoch will be sent */
1372 hs_my_epoch = hs_epoch;
1373 /* Generate random */
1374 for (randomidx = 0; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1376 AV_WB32(hs_s1 + 8 + randomidx, av_get_random_seed());
1378 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1379 RTMP_HANDSHAKE_PACKET_SIZE);
1381 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1385 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1386 RTMP_HANDSHAKE_PACKET_SIZE);
1388 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1392 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1393 RTMP_HANDSHAKE_PACKET_SIZE);
1395 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1398 if (temp != hs_my_epoch)
1399 av_log(s, AV_LOG_WARNING,
1400 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1401 if (memcmp(buffer + 8, hs_s1 + 8,
1402 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1403 av_log(s, AV_LOG_WARNING,
1404 "Erroneous C2 Message random does not match up\n");
1409 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1411 RTMPContext *rt = s->priv_data;
1414 if (pkt->data_size < 4) {
1415 av_log(s, AV_LOG_ERROR,
1416 "Too short chunk size change packet (%d)\n",
1418 return AVERROR_INVALIDDATA;
1421 if (!rt->is_input) {
1422 /* Send the same chunk size change packet back to the server,
1423 * setting the outgoing chunk size to the same as the incoming one. */
1424 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1425 rt->prev_pkt[1])) < 0)
1427 rt->out_chunk_size = AV_RB32(pkt->data);
1430 rt->in_chunk_size = AV_RB32(pkt->data);
1431 if (rt->in_chunk_size <= 0) {
1432 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1434 return AVERROR_INVALIDDATA;
1436 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1442 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1444 RTMPContext *rt = s->priv_data;
1447 if (pkt->data_size < 2) {
1448 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1450 return AVERROR_INVALIDDATA;
1453 t = AV_RB16(pkt->data);
1455 if ((ret = gen_pong(s, rt, pkt)) < 0)
1457 } else if (t == 26) {
1459 if ((ret = gen_swf_verification(s, rt)) < 0)
1462 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1469 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1471 RTMPContext *rt = s->priv_data;
1473 if (pkt->data_size < 4) {
1474 av_log(s, AV_LOG_ERROR,
1475 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1477 return AVERROR_INVALIDDATA;
1480 rt->client_report_size = AV_RB32(pkt->data);
1481 if (rt->client_report_size <= 0) {
1482 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1483 rt->client_report_size);
1484 return AVERROR_INVALIDDATA;
1487 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1488 rt->client_report_size >>= 1;
1493 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1495 RTMPContext *rt = s->priv_data;
1497 if (pkt->data_size < 4) {
1498 av_log(s, AV_LOG_ERROR,
1499 "Too short server bandwidth report packet (%d)\n",
1501 return AVERROR_INVALIDDATA;
1504 rt->server_bw = AV_RB32(pkt->data);
1505 if (rt->server_bw <= 0) {
1506 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1508 return AVERROR_INVALIDDATA;
1510 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1515 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1517 const uint8_t *data_end = pkt->data + pkt->data_size;
1518 char *tracked_method = NULL;
1519 int level = AV_LOG_ERROR;
1520 uint8_t tmpstr[256];
1523 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1526 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1527 "description", tmpstr, sizeof(tmpstr))) {
1528 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1529 !strcmp(tracked_method, "releaseStream") ||
1530 !strcmp(tracked_method, "FCSubscribe") ||
1531 !strcmp(tracked_method, "FCPublish"))) {
1532 /* Gracefully ignore Adobe-specific historical artifact errors. */
1533 level = AV_LOG_WARNING;
1537 av_log(s, level, "Server error: %s\n", tmpstr);
1540 av_free(tracked_method);
1544 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1546 RTMPContext *rt = s->priv_data;
1550 char statusmsg[128];
1553 const uint8_t *p = pkt->data;
1555 RTMPPacket spkt = { 0 };
1559 bytestream2_init(&gbc, p, pkt->data_size);
1560 if (ff_amf_read_string(&gbc, command, sizeof(command),
1562 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1563 return AVERROR_INVALIDDATA;
1566 ret = ff_amf_read_number(&gbc, &seqnum);
1569 ret = ff_amf_read_null(&gbc);
1572 if (!strcmp(command, "FCPublish") ||
1573 !strcmp(command, "publish")) {
1574 ret = ff_amf_read_string(&gbc, filename,
1575 sizeof(filename), &stringlen);
1578 pchar = strrchr(s->filename, '/');
1580 av_log(s, AV_LOG_WARNING,
1581 "Unable to find / in url %s, bad format\n",
1583 pchar = s->filename;
1586 if (strcmp(pchar, filename))
1587 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1588 " %s\n", filename, pchar);
1590 rt->state = STATE_RECEIVING;
1593 if (!strcmp(command, "FCPublish")) {
1594 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1596 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1597 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1601 ff_amf_write_string(&pp, "onFCPublish");
1602 } else if (!strcmp(command, "publish")) {
1604 // Send Stream Begin 1
1605 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1606 RTMP_PT_PING, 0, 6)) < 0) {
1607 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1611 bytestream2_init_writer(&pbc, pp, spkt.data_size);
1612 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1613 bytestream2_put_be32(&pbc, rt->nb_streamid);
1614 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1616 ff_rtmp_packet_destroy(&spkt);
1620 // Send onStatus(NetStream.Publish.Start)
1621 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1623 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1624 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1627 spkt.extra = pkt->extra;
1629 ff_amf_write_string(&pp, "onStatus");
1630 ff_amf_write_number(&pp, 0);
1631 ff_amf_write_null(&pp);
1633 ff_amf_write_object_start(&pp);
1634 ff_amf_write_field_name(&pp, "level");
1635 ff_amf_write_string(&pp, "status");
1636 ff_amf_write_field_name(&pp, "code");
1637 ff_amf_write_string(&pp, "NetStream.Publish.Start");
1638 ff_amf_write_field_name(&pp, "description");
1639 snprintf(statusmsg, sizeof(statusmsg),
1640 "%s is now published", filename);
1641 ff_amf_write_string(&pp, statusmsg);
1642 ff_amf_write_field_name(&pp, "details");
1643 ff_amf_write_string(&pp, filename);
1644 ff_amf_write_field_name(&pp, "clientid");
1645 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1646 ff_amf_write_string(&pp, statusmsg);
1647 ff_amf_write_object_end(&pp);
1650 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1652 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1653 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1657 ff_amf_write_string(&pp, "_result");
1658 ff_amf_write_number(&pp, seqnum);
1659 ff_amf_write_null(&pp);
1660 if (!strcmp(command, "createStream")) {
1662 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1663 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1664 ff_amf_write_number(&pp, rt->nb_streamid);
1665 /* By now we don't control which streams are removed in
1666 * deleteStream. There is no stream creation control
1667 * if a client creates more than 2^32 - 2 streams. */
1670 spkt.data_size = pp - spkt.data;
1671 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1673 ff_rtmp_packet_destroy(&spkt);
1677 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1679 RTMPContext *rt = s->priv_data;
1680 char *tracked_method = NULL;
1683 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1686 if (!tracked_method) {
1687 /* Ignore this reply when the current method is not tracked. */
1691 if (!memcmp(tracked_method, "connect", 7)) {
1692 if (!rt->is_input) {
1693 if ((ret = gen_release_stream(s, rt)) < 0)
1696 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1699 if ((ret = gen_server_bw(s, rt)) < 0)
1703 if ((ret = gen_create_stream(s, rt)) < 0)
1707 /* Send the FCSubscribe command when the name of live
1708 * stream is defined by the user or if it's a live stream. */
1709 if (rt->subscribe) {
1710 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1712 } else if (rt->live == -1) {
1713 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1717 } else if (!memcmp(tracked_method, "createStream", 12)) {
1718 //extract a number from the result
1719 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1720 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1722 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1725 if (!rt->is_input) {
1726 if ((ret = gen_publish(s, rt)) < 0)
1729 if ((ret = gen_play(s, rt)) < 0)
1731 if ((ret = gen_buffer_time(s, rt)) < 0)
1737 av_free(tracked_method);
1741 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1743 RTMPContext *rt = s->priv_data;
1744 const uint8_t *data_end = pkt->data + pkt->data_size;
1745 const uint8_t *ptr = pkt->data + 11;
1746 uint8_t tmpstr[256];
1749 for (i = 0; i < 2; i++) {
1750 t = ff_amf_tag_size(ptr, data_end);
1756 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1757 if (!t && !strcmp(tmpstr, "error")) {
1758 if (!ff_amf_get_field_value(ptr, data_end,
1759 "description", tmpstr, sizeof(tmpstr)))
1760 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1764 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1765 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1766 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1767 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1768 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1773 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1775 RTMPContext *rt = s->priv_data;
1778 //TODO: check for the messages sent for wrong state?
1779 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
1780 if ((ret = handle_invoke_error(s, pkt)) < 0)
1782 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
1783 if ((ret = handle_invoke_result(s, pkt)) < 0)
1785 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
1786 if ((ret = handle_invoke_status(s, pkt)) < 0)
1788 } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
1789 if ((ret = gen_check_bw(s, rt)) < 0)
1791 } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
1792 !memcmp(pkt->data, "\002\000\011FCPublish", 12) ||
1793 !memcmp(pkt->data, "\002\000\007publish", 10) ||
1794 !memcmp(pkt->data, "\002\000\010_checkbw", 11) ||
1795 !memcmp(pkt->data, "\002\000\014createStream", 15)) {
1796 if (ret = send_invoke_response(s, pkt) < 0)
1803 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
1804 RTMPContext *rt = s->priv_data;
1805 const uint8_t *p = NULL;
1807 uint8_t commandbuffer[64];
1808 char statusmsg[128];
1814 const uint8_t *datatowrite;
1815 unsigned datatowritelength;
1818 bytestream2_init(&gbc, p, pkt->data_size);
1819 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
1821 return AVERROR_INVALIDDATA;
1822 if (!strcmp(commandbuffer, "@setDataFrame")) {
1823 datatowrite = gbc.buffer;
1824 datatowritelength = bytestream2_get_bytes_left(&gbc);
1825 if (ff_amf_read_string(&gbc, statusmsg,
1826 sizeof(statusmsg), &stringlen))
1827 return AVERROR_INVALIDDATA;
1828 if (strcmp(statusmsg, "onMetaData")) {
1829 av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
1834 /* Provide ECMAArray to flv */
1835 ts = pkt->timestamp;
1837 // generate packet header and put data into buffer for FLV demuxer
1838 if (rt->flv_off < rt->flv_size) {
1839 old_flv_size = rt->flv_size;
1840 rt->flv_size += datatowritelength + 15;
1843 rt->flv_size = datatowritelength + 15;
1847 cp = av_realloc(rt->flv_data, rt->flv_size);
1849 return AVERROR(ENOMEM);
1851 bytestream2_init_writer(&pbc, cp, rt->flv_size);
1852 bytestream2_skip_p(&pbc, old_flv_size);
1853 bytestream2_put_byte(&pbc, pkt->type);
1854 bytestream2_put_be24(&pbc, datatowritelength);
1855 bytestream2_put_be24(&pbc, ts);
1856 bytestream2_put_byte(&pbc, ts >> 24);
1857 bytestream2_put_be24(&pbc, 0);
1858 bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
1859 bytestream2_put_be32(&pbc, 0);
1865 * Parse received packet and possibly perform some action depending on
1866 * the packet contents.
1867 * @return 0 for no errors, negative values for serious errors which prevent
1868 * further communications, positive values for uncritical errors
1870 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
1875 ff_rtmp_packet_dump(s, pkt);
1878 switch (pkt->type) {
1879 case RTMP_PT_BYTES_READ:
1880 av_dlog(s, "received bytes read report\n");
1882 case RTMP_PT_CHUNK_SIZE:
1883 if ((ret = handle_chunk_size(s, pkt)) < 0)
1887 if ((ret = handle_ping(s, pkt)) < 0)
1890 case RTMP_PT_CLIENT_BW:
1891 if ((ret = handle_client_bw(s, pkt)) < 0)
1894 case RTMP_PT_SERVER_BW:
1895 if ((ret = handle_server_bw(s, pkt)) < 0)
1898 case RTMP_PT_INVOKE:
1899 if ((ret = handle_invoke(s, pkt)) < 0)
1904 case RTMP_PT_METADATA:
1905 case RTMP_PT_NOTIFY:
1906 /* Audio, Video and Metadata packets are parsed in get_packet() */
1909 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
1916 * Interact with the server by receiving and sending RTMP packets until
1917 * there is some significant data (media data or expected status notification).
1919 * @param s reading context
1920 * @param for_header non-zero value tells function to work until it
1921 * gets notification from the server that playing has been started,
1922 * otherwise function will work until some media data is received (or
1924 * @return 0 for successful operation, negative value in case of error
1926 static int get_packet(URLContext *s, int for_header)
1928 RTMPContext *rt = s->priv_data;
1931 const uint8_t *next;
1933 uint32_t ts, cts, pts=0;
1935 if (rt->state == STATE_STOPPED)
1939 RTMPPacket rpkt = { 0 };
1940 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
1941 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
1943 return AVERROR(EAGAIN);
1945 return AVERROR(EIO);
1948 rt->bytes_read += ret;
1949 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
1950 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
1951 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
1953 rt->last_bytes_read = rt->bytes_read;
1956 ret = rtmp_parse_result(s, rt, &rpkt);
1957 if (ret < 0) {//serious error in current packet
1958 ff_rtmp_packet_destroy(&rpkt);
1961 if (rt->state == STATE_STOPPED) {
1962 ff_rtmp_packet_destroy(&rpkt);
1965 if (for_header && (rt->state == STATE_PLAYING ||
1966 rt->state == STATE_PUBLISHING ||
1967 rt->state == STATE_RECEIVING)) {
1968 ff_rtmp_packet_destroy(&rpkt);
1971 if (!rpkt.data_size || !rt->is_input) {
1972 ff_rtmp_packet_destroy(&rpkt);
1975 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
1976 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
1977 ts = rpkt.timestamp;
1979 // generate packet header and put data into buffer for FLV demuxer
1981 rt->flv_size = rpkt.data_size + 15;
1982 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
1983 bytestream_put_byte(&p, rpkt.type);
1984 bytestream_put_be24(&p, rpkt.data_size);
1985 bytestream_put_be24(&p, ts);
1986 bytestream_put_byte(&p, ts >> 24);
1987 bytestream_put_be24(&p, 0);
1988 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
1989 bytestream_put_be32(&p, 0);
1990 ff_rtmp_packet_destroy(&rpkt);
1992 } else if (rpkt.type == RTMP_PT_NOTIFY) {
1993 ret = handle_notify(s, &rpkt);
1994 ff_rtmp_packet_destroy(&rpkt);
1996 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2000 } else if (rpkt.type == RTMP_PT_METADATA) {
2001 // we got raw FLV data, make it available for FLV demuxer
2003 rt->flv_size = rpkt.data_size;
2004 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2005 /* rewrite timestamps */
2007 ts = rpkt.timestamp;
2008 while (next - rpkt.data < rpkt.data_size - 11) {
2010 data_size = bytestream_get_be24(&next);
2012 cts = bytestream_get_be24(&next);
2013 cts |= bytestream_get_byte(&next) << 24;
2018 bytestream_put_be24(&p, ts);
2019 bytestream_put_byte(&p, ts >> 24);
2020 next += data_size + 3 + 4;
2022 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
2023 ff_rtmp_packet_destroy(&rpkt);
2026 ff_rtmp_packet_destroy(&rpkt);
2030 static int rtmp_close(URLContext *h)
2032 RTMPContext *rt = h->priv_data;
2035 if (!rt->is_input) {
2036 rt->flv_data = NULL;
2037 if (rt->out_pkt.data_size)
2038 ff_rtmp_packet_destroy(&rt->out_pkt);
2039 if (rt->state > STATE_FCPUBLISH)
2040 ret = gen_fcunpublish_stream(h, rt);
2042 if (rt->state > STATE_HANDSHAKED)
2043 ret = gen_delete_stream(h, rt);
2045 free_tracked_methods(rt);
2046 av_freep(&rt->flv_data);
2047 ffurl_close(rt->stream);
2052 * Open RTMP connection and verify that the stream can be played.
2054 * URL syntax: rtmp://server[:port][/app][/playpath]
2055 * where 'app' is first one or two directories in the path
2056 * (e.g. /ondemand/, /flash/live/, etc.)
2057 * and 'playpath' is a file name (the rest of the path,
2058 * may be prefixed with "mp4:")
2060 static int rtmp_open(URLContext *s, const char *uri, int flags)
2062 RTMPContext *rt = s->priv_data;
2063 char proto[8], hostname[256], path[1024], *fname;
2067 AVDictionary *opts = NULL;
2070 if (rt->listen_timeout > 0)
2073 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2075 av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
2076 path, sizeof(path), s->filename);
2078 if (rt->listen && strcmp(proto, "rtmp")) {
2079 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2081 return AVERROR(EINVAL);
2083 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2084 if (!strcmp(proto, "rtmpts"))
2085 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2087 /* open the http tunneling connection */
2088 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2089 } else if (!strcmp(proto, "rtmps")) {
2090 /* open the tls connection */
2092 port = RTMPS_DEFAULT_PORT;
2093 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2094 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2095 if (!strcmp(proto, "rtmpte"))
2096 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2098 /* open the encrypted connection */
2099 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2102 /* open the tcp connection */
2104 port = RTMP_DEFAULT_PORT;
2106 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2107 "?listen&listen_timeout=%d",
2108 rt->listen_timeout * 1000);
2110 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2113 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2114 &s->interrupt_callback, &opts)) < 0) {
2115 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2119 if (rt->swfverify) {
2120 if ((ret = rtmp_calc_swfhash(s)) < 0)
2124 rt->state = STATE_START;
2125 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2127 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2130 rt->out_chunk_size = 128;
2131 rt->in_chunk_size = 128; // Probably overwritten later
2132 rt->state = STATE_HANDSHAKED;
2134 // Keep the application name when it has been defined by the user.
2137 rt->app = av_malloc(APP_MAX_LENGTH);
2139 ret = AVERROR(ENOMEM);
2143 //extract "app" part from path
2144 if (!strncmp(path, "/ondemand/", 10)) {
2146 memcpy(rt->app, "ondemand", 9);
2148 char *next = *path ? path + 1 : path;
2149 char *p = strchr(next, '/');
2154 // make sure we do not mismatch a playpath for an application instance
2155 char *c = strchr(p + 1, ':');
2156 fname = strchr(p + 1, '/');
2157 if (!fname || (c && c < fname)) {
2159 av_strlcpy(rt->app, path + 1, p - path);
2162 av_strlcpy(rt->app, path + 1, fname - path - 1);
2168 // The name of application has been defined by the user, override it.
2173 if (!rt->playpath) {
2174 int len = strlen(fname);
2176 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2177 if (!rt->playpath) {
2178 ret = AVERROR(ENOMEM);
2182 if (!strchr(fname, ':') && len >= 4 &&
2183 (!strcmp(fname + len - 4, ".f4v") ||
2184 !strcmp(fname + len - 4, ".mp4"))) {
2185 memcpy(rt->playpath, "mp4:", 5);
2186 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2187 fname[len - 4] = '\0';
2189 rt->playpath[0] = 0;
2191 strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5);
2195 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2197 ret = AVERROR(ENOMEM);
2200 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2201 port, "/%s", rt->app);
2204 if (!rt->flashver) {
2205 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2206 if (!rt->flashver) {
2207 ret = AVERROR(ENOMEM);
2211 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2212 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2213 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2215 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2216 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2220 rt->client_report_size = 1048576;
2222 rt->last_bytes_read = 0;
2223 rt->server_bw = 2500000;
2225 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2226 proto, path, rt->app, rt->playpath);
2228 if ((ret = gen_connect(s, rt)) < 0)
2231 if (read_connect(s, s->priv_data) < 0)
2237 ret = get_packet(s, 1);
2238 } while (ret == EAGAIN);
2243 // generate FLV header for demuxer
2245 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2247 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2250 rt->flv_data = NULL;
2252 rt->skip_bytes = 13;
2255 s->max_packet_size = rt->stream->max_packet_size;
2260 av_dict_free(&opts);
2265 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2267 RTMPContext *rt = s->priv_data;
2268 int orig_size = size;
2272 int data_left = rt->flv_size - rt->flv_off;
2274 if (data_left >= size) {
2275 memcpy(buf, rt->flv_data + rt->flv_off, size);
2276 rt->flv_off += size;
2279 if (data_left > 0) {
2280 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2283 rt->flv_off = rt->flv_size;
2286 if ((ret = get_packet(s, 0)) < 0)
2292 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2294 RTMPContext *rt = s->priv_data;
2295 int size_temp = size;
2296 int pktsize, pkttype;
2298 const uint8_t *buf_temp = buf;
2303 if (rt->skip_bytes) {
2304 int skip = FFMIN(rt->skip_bytes, size_temp);
2307 rt->skip_bytes -= skip;
2311 if (rt->flv_header_bytes < 11) {
2312 const uint8_t *header = rt->flv_header;
2313 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2314 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2315 rt->flv_header_bytes += copy;
2317 if (rt->flv_header_bytes < 11)
2320 pkttype = bytestream_get_byte(&header);
2321 pktsize = bytestream_get_be24(&header);
2322 ts = bytestream_get_be24(&header);
2323 ts |= bytestream_get_byte(&header) << 24;
2324 bytestream_get_be24(&header);
2325 rt->flv_size = pktsize;
2327 //force 12bytes header
2328 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2329 pkttype == RTMP_PT_NOTIFY) {
2330 if (pkttype == RTMP_PT_NOTIFY)
2332 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2335 //this can be a big packet, it's better to send it right here
2336 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2337 pkttype, ts, pktsize)) < 0)
2340 rt->out_pkt.extra = rt->main_channel_id;
2341 rt->flv_data = rt->out_pkt.data;
2343 if (pkttype == RTMP_PT_NOTIFY)
2344 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2347 if (rt->flv_size - rt->flv_off > size_temp) {
2348 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2349 rt->flv_off += size_temp;
2352 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2353 size_temp -= rt->flv_size - rt->flv_off;
2354 rt->flv_off += rt->flv_size - rt->flv_off;
2357 if (rt->flv_off == rt->flv_size) {
2360 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2364 rt->flv_header_bytes = 0;
2365 rt->flv_nb_packets++;
2367 } while (buf_temp - buf < size);
2369 if (rt->flv_nb_packets < rt->flush_interval)
2371 rt->flv_nb_packets = 0;
2373 /* set stream into nonblocking mode */
2374 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2376 /* try to read one byte from the stream */
2377 ret = ffurl_read(rt->stream, &c, 1);
2379 /* switch the stream back into blocking mode */
2380 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2382 if (ret == AVERROR(EAGAIN)) {
2383 /* no incoming data to handle */
2385 } else if (ret < 0) {
2387 } else if (ret == 1) {
2388 RTMPPacket rpkt = { 0 };
2390 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2392 rt->prev_pkt[0], c)) <= 0)
2395 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2398 ff_rtmp_packet_destroy(&rpkt);
2404 #define OFFSET(x) offsetof(RTMPContext, x)
2405 #define DEC AV_OPT_FLAG_DECODING_PARAM
2406 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2408 static const AVOption rtmp_options[] = {
2409 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2410 {"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},
2411 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2412 {"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},
2413 {"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},
2414 {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
2415 {"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
2416 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
2417 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"},
2418 {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2419 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2420 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2421 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2422 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {0}, 0, INT_MAX, DEC},
2423 {"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},
2424 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2425 {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2426 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2427 {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1", OFFSET(listen_timeout), AV_OPT_TYPE_INT, {-1}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2431 #define RTMP_PROTOCOL(flavor) \
2432 static const AVClass flavor##_class = { \
2433 .class_name = #flavor, \
2434 .item_name = av_default_item_name, \
2435 .option = rtmp_options, \
2436 .version = LIBAVUTIL_VERSION_INT, \
2439 URLProtocol ff_##flavor##_protocol = { \
2441 .url_open = rtmp_open, \
2442 .url_read = rtmp_read, \
2443 .url_write = rtmp_write, \
2444 .url_close = rtmp_close, \
2445 .priv_data_size = sizeof(RTMPContext), \
2446 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2447 .priv_data_class= &flavor##_class, \
2452 RTMP_PROTOCOL(rtmpe)
2453 RTMP_PROTOCOL(rtmps)
2454 RTMP_PROTOCOL(rtmpt)
2455 RTMP_PROTOCOL(rtmpte)
2456 RTMP_PROTOCOL(rtmpts)