]> git.sesse.net Git - ffmpeg/blob - libavformat/rtmpproto.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavformat / rtmpproto.c
1 /*
2  * RTMP network protocol
3  * Copyright (c) 2009 Kostya Shishkov
4  *
5  * This file is part of FFmpeg.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 /**
23  * @file
24  * RTMP protocol
25  */
26
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"
33 #include "avformat.h"
34 #include "internal.h"
35
36 #include "network.h"
37
38 #include "flv.h"
39 #include "rtmp.h"
40 #include "rtmppkt.h"
41 #include "url.h"
42
43 //#define DEBUG
44
45 #define APP_MAX_LENGTH 128
46 #define PLAYPATH_MAX_LENGTH 256
47 #define TCURL_MAX_LENGTH 512
48 #define FLASHVER_MAX_LENGTH 64
49
50 /** RTMP protocol handler state */
51 typedef enum {
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
61 } ClientState;
62
63 /** protocol handler context */
64 typedef struct RTMPContext {
65     const AVClass *class;
66     URLContext*   stream;                     ///< TCP stream used in interactions with RTMP server
67     RTMPPacket    prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
68     int           chunk_size;                 ///< size of the chunks RTMP packets are divided into
69     int           is_input;                   ///< input/output flag
70     char          *playpath;                  ///< stream identifier to play (with possible "mp4:" prefix)
71     int           live;                       ///< 0: recorded, -1: live, -2: both
72     char          *app;                       ///< name of application
73     char          *conn;                      ///< append arbitrary AMF data to the Connect message
74     ClientState   state;                      ///< current state
75     int           main_channel_id;            ///< an additional channel ID which is used for some invocations
76     uint8_t*      flv_data;                   ///< buffer with data for demuxer
77     int           flv_size;                   ///< current buffer size
78     int           flv_off;                    ///< number of bytes read from current buffer
79     int           flv_nb_packets;             ///< number of flv packets published
80     RTMPPacket    out_pkt;                    ///< rtmp packet, created from flv a/v or metadata (for output)
81     uint32_t      client_report_size;         ///< number of bytes after which client should report to server
82     uint32_t      bytes_read;                 ///< number of bytes read from server
83     uint32_t      last_bytes_read;            ///< number of bytes read last reported to server
84     int           skip_bytes;                 ///< number of bytes to skip from the input FLV stream in the next write call
85     uint8_t       flv_header[11];             ///< partial incoming flv packet header
86     int           flv_header_bytes;           ///< number of initialized bytes in flv_header
87     int           nb_invokes;                 ///< keeps track of invoke messages
88     int           create_stream_invoke;       ///< invoke id for the create stream command
89     char*         tcurl;                      ///< url of the target stream
90     char*         flashver;                   ///< version of the flash plugin
91     char*         swfurl;                     ///< url of the swf player
92     int           server_bw;                  ///< server bandwidth
93     int           client_buffer_time;         ///< client buffer time in ms
94     int           flush_interval;             ///< number of packets flushed in the same request (RTMPT only)
95 } RTMPContext;
96
97 #define PLAYER_KEY_OPEN_PART_LEN 30   ///< length of partial key used for first client digest signing
98 /** Client key used for digest signing */
99 static const uint8_t rtmp_player_key[] = {
100     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
101     'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
102
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
106 };
107
108 #define SERVER_KEY_OPEN_PART_LEN 36   ///< length of partial key used for first server digest signing
109 /** Key used for RTMP server digest signing */
110 static const uint8_t rtmp_server_key[] = {
111     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
112     'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
113     'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
114
115     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
116     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
117     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
118 };
119
120 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
121 {
122     char *field, *value;
123     char type;
124
125     /* The type must be B for Boolean, N for number, S for string, O for
126      * object, or Z for null. For Booleans the data must be either 0 or 1 for
127      * FALSE or TRUE, respectively. Likewise for Objects the data must be
128      * 0 or 1 to end or begin an object, respectively. Data items in subobjects
129      * may be named, by prefixing the type with 'N' and specifying the name
130      * before the value (ie. NB:myFlag:1). This option may be used multiple times
131      * to construct arbitrary AMF sequences. */
132     if (param[0] && param[1] == ':') {
133         type = param[0];
134         value = param + 2;
135     } else if (param[0] == 'N' && param[1] && param[2] == ':') {
136         type = param[1];
137         field = param + 3;
138         value = strchr(field, ':');
139         if (!value)
140             goto fail;
141         *value = '\0';
142         value++;
143
144         if (!field || !value)
145             goto fail;
146
147         ff_amf_write_field_name(p, field);
148     } else {
149         goto fail;
150     }
151
152     switch (type) {
153     case 'B':
154         ff_amf_write_bool(p, value[0] != '0');
155         break;
156     case 'S':
157         ff_amf_write_string(p, value);
158         break;
159     case 'N':
160         ff_amf_write_number(p, strtod(value, NULL));
161         break;
162     case 'Z':
163         ff_amf_write_null(p);
164         break;
165     case 'O':
166         if (value[0] != '0')
167             ff_amf_write_object_start(p);
168         else
169             ff_amf_write_object_end(p);
170         break;
171     default:
172         goto fail;
173         break;
174     }
175
176     return 0;
177
178 fail:
179     av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
180     return AVERROR(EINVAL);
181 }
182
183 /**
184  * Generate 'connect' call and send it to the server.
185  */
186 static int gen_connect(URLContext *s, RTMPContext *rt)
187 {
188     RTMPPacket pkt;
189     uint8_t *p;
190     int ret;
191
192     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
193                                      0, 4096)) < 0)
194         return ret;
195
196     p = pkt.data;
197
198     ff_amf_write_string(&p, "connect");
199     ff_amf_write_number(&p, ++rt->nb_invokes);
200     ff_amf_write_object_start(&p);
201     ff_amf_write_field_name(&p, "app");
202     ff_amf_write_string(&p, rt->app);
203
204     if (!rt->is_input) {
205         ff_amf_write_field_name(&p, "type");
206         ff_amf_write_string(&p, "nonprivate");
207     }
208     ff_amf_write_field_name(&p, "flashVer");
209     ff_amf_write_string(&p, rt->flashver);
210
211     if (rt->swfurl) {
212         ff_amf_write_field_name(&p, "swfUrl");
213         ff_amf_write_string(&p, rt->swfurl);
214     }
215
216     ff_amf_write_field_name(&p, "tcUrl");
217     ff_amf_write_string(&p, rt->tcurl);
218     if (rt->is_input) {
219         ff_amf_write_field_name(&p, "fpad");
220         ff_amf_write_bool(&p, 0);
221         ff_amf_write_field_name(&p, "capabilities");
222         ff_amf_write_number(&p, 15.0);
223
224         /* Tell the server we support all the audio codecs except
225          * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
226          * which are unused in the RTMP protocol implementation. */
227         ff_amf_write_field_name(&p, "audioCodecs");
228         ff_amf_write_number(&p, 4071.0);
229         ff_amf_write_field_name(&p, "videoCodecs");
230         ff_amf_write_number(&p, 252.0);
231         ff_amf_write_field_name(&p, "videoFunction");
232         ff_amf_write_number(&p, 1.0);
233     }
234     ff_amf_write_object_end(&p);
235
236     if (rt->conn) {
237         char *param = rt->conn;
238
239         // Write arbitrary AMF data to the Connect message.
240         while (param != NULL) {
241             char *sep;
242             param += strspn(param, " ");
243             if (!*param)
244                 break;
245             sep = strchr(param, ' ');
246             if (sep)
247                 *sep = '\0';
248             if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
249                 // Invalid AMF parameter.
250                 ff_rtmp_packet_destroy(&pkt);
251                 return ret;
252             }
253
254             if (sep)
255                 param = sep + 1;
256             else
257                 break;
258         }
259     }
260
261     pkt.data_size = p - pkt.data;
262
263     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
264                                rt->prev_pkt[1]);
265     ff_rtmp_packet_destroy(&pkt);
266
267     return ret;
268 }
269
270 /**
271  * Generate 'releaseStream' call and send it to the server. It should make
272  * the server release some channel for media streams.
273  */
274 static int gen_release_stream(URLContext *s, RTMPContext *rt)
275 {
276     RTMPPacket pkt;
277     uint8_t *p;
278     int ret;
279
280     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
281                                      0, 29 + strlen(rt->playpath))) < 0)
282         return ret;
283
284     av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
285     p = pkt.data;
286     ff_amf_write_string(&p, "releaseStream");
287     ff_amf_write_number(&p, ++rt->nb_invokes);
288     ff_amf_write_null(&p);
289     ff_amf_write_string(&p, rt->playpath);
290
291     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
292                                rt->prev_pkt[1]);
293     ff_rtmp_packet_destroy(&pkt);
294
295     return ret;
296 }
297
298 /**
299  * Generate 'FCPublish' call and send it to the server. It should make
300  * the server preapare for receiving media streams.
301  */
302 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
303 {
304     RTMPPacket pkt;
305     uint8_t *p;
306     int ret;
307
308     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
309                                      0, 25 + strlen(rt->playpath))) < 0)
310         return ret;
311
312     av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
313     p = pkt.data;
314     ff_amf_write_string(&p, "FCPublish");
315     ff_amf_write_number(&p, ++rt->nb_invokes);
316     ff_amf_write_null(&p);
317     ff_amf_write_string(&p, rt->playpath);
318
319     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
320                                rt->prev_pkt[1]);
321     ff_rtmp_packet_destroy(&pkt);
322
323     return ret;
324 }
325
326 /**
327  * Generate 'FCUnpublish' call and send it to the server. It should make
328  * the server destroy stream.
329  */
330 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
331 {
332     RTMPPacket pkt;
333     uint8_t *p;
334     int ret;
335
336     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
337                                      0, 27 + strlen(rt->playpath))) < 0)
338         return ret;
339
340     av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
341     p = pkt.data;
342     ff_amf_write_string(&p, "FCUnpublish");
343     ff_amf_write_number(&p, ++rt->nb_invokes);
344     ff_amf_write_null(&p);
345     ff_amf_write_string(&p, rt->playpath);
346
347     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
348                                rt->prev_pkt[1]);
349     ff_rtmp_packet_destroy(&pkt);
350
351     return ret;
352 }
353
354 /**
355  * Generate 'createStream' call and send it to the server. It should make
356  * the server allocate some channel for media streams.
357  */
358 static int gen_create_stream(URLContext *s, RTMPContext *rt)
359 {
360     RTMPPacket pkt;
361     uint8_t *p;
362     int ret;
363
364     av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
365
366     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
367                                      0, 25)) < 0)
368         return ret;
369
370     p = pkt.data;
371     ff_amf_write_string(&p, "createStream");
372     ff_amf_write_number(&p, ++rt->nb_invokes);
373     ff_amf_write_null(&p);
374     rt->create_stream_invoke = rt->nb_invokes;
375
376     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
377                                rt->prev_pkt[1]);
378     ff_rtmp_packet_destroy(&pkt);
379
380     return ret;
381 }
382
383
384 /**
385  * Generate 'deleteStream' call and send it to the server. It should make
386  * the server remove some channel for media streams.
387  */
388 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
389 {
390     RTMPPacket pkt;
391     uint8_t *p;
392     int ret;
393
394     av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
395
396     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
397                                      0, 34)) < 0)
398         return ret;
399
400     p = pkt.data;
401     ff_amf_write_string(&p, "deleteStream");
402     ff_amf_write_number(&p, ++rt->nb_invokes);
403     ff_amf_write_null(&p);
404     ff_amf_write_number(&p, rt->main_channel_id);
405
406     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
407                                rt->prev_pkt[1]);
408     ff_rtmp_packet_destroy(&pkt);
409
410     return ret;
411 }
412
413 /**
414  * Generate client buffer time and send it to the server.
415  */
416 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
417 {
418     RTMPPacket pkt;
419     uint8_t *p;
420     int ret;
421
422     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
423                                      1, 10)) < 0)
424         return ret;
425
426     p = pkt.data;
427     bytestream_put_be16(&p, 3);
428     bytestream_put_be32(&p, rt->main_channel_id);
429     bytestream_put_be32(&p, rt->client_buffer_time);
430
431     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
432                                rt->prev_pkt[1]);
433     ff_rtmp_packet_destroy(&pkt);
434
435     return ret;
436 }
437
438 /**
439  * Generate 'play' call and send it to the server, then ping the server
440  * to start actual playing.
441  */
442 static int gen_play(URLContext *s, RTMPContext *rt)
443 {
444     RTMPPacket pkt;
445     uint8_t *p;
446     int ret;
447
448     av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
449
450     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
451                                      0, 29 + strlen(rt->playpath))) < 0)
452         return ret;
453
454     pkt.extra = rt->main_channel_id;
455
456     p = pkt.data;
457     ff_amf_write_string(&p, "play");
458     ff_amf_write_number(&p, ++rt->nb_invokes);
459     ff_amf_write_null(&p);
460     ff_amf_write_string(&p, rt->playpath);
461     ff_amf_write_number(&p, rt->live);
462
463     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
464                                rt->prev_pkt[1]);
465     ff_rtmp_packet_destroy(&pkt);
466
467     return ret;
468 }
469
470 /**
471  * Generate 'publish' call and send it to the server.
472  */
473 static int gen_publish(URLContext *s, RTMPContext *rt)
474 {
475     RTMPPacket pkt;
476     uint8_t *p;
477     int ret;
478
479     av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
480
481     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
482                                      0, 30 + strlen(rt->playpath))) < 0)
483         return ret;
484
485     pkt.extra = rt->main_channel_id;
486
487     p = pkt.data;
488     ff_amf_write_string(&p, "publish");
489     ff_amf_write_number(&p, ++rt->nb_invokes);
490     ff_amf_write_null(&p);
491     ff_amf_write_string(&p, rt->playpath);
492     ff_amf_write_string(&p, "live");
493
494     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
495                                rt->prev_pkt[1]);
496     ff_rtmp_packet_destroy(&pkt);
497
498     return ret;
499 }
500
501 /**
502  * Generate ping reply and send it to the server.
503  */
504 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
505 {
506     RTMPPacket pkt;
507     uint8_t *p;
508     int ret;
509
510     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
511                                      ppkt->timestamp + 1, 6)) < 0)
512         return ret;
513
514     p = pkt.data;
515     bytestream_put_be16(&p, 7);
516     bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
517     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
518                                rt->prev_pkt[1]);
519     ff_rtmp_packet_destroy(&pkt);
520
521     return ret;
522 }
523
524 /**
525  * Generate server bandwidth message and send it to the server.
526  */
527 static int gen_server_bw(URLContext *s, RTMPContext *rt)
528 {
529     RTMPPacket pkt;
530     uint8_t *p;
531     int ret;
532
533     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
534                                      0, 4)) < 0)
535         return ret;
536
537     p = pkt.data;
538     bytestream_put_be32(&p, rt->server_bw);
539     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
540                                rt->prev_pkt[1]);
541     ff_rtmp_packet_destroy(&pkt);
542
543     return ret;
544 }
545
546 /**
547  * Generate check bandwidth message and send it to the server.
548  */
549 static int gen_check_bw(URLContext *s, RTMPContext *rt)
550 {
551     RTMPPacket pkt;
552     uint8_t *p;
553     int ret;
554
555     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
556                                      0, 21)) < 0)
557         return ret;
558
559     p = pkt.data;
560     ff_amf_write_string(&p, "_checkbw");
561     ff_amf_write_number(&p, ++rt->nb_invokes);
562     ff_amf_write_null(&p);
563
564     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
565                                rt->prev_pkt[1]);
566     ff_rtmp_packet_destroy(&pkt);
567
568     return ret;
569 }
570
571 /**
572  * Generate report on bytes read so far and send it to the server.
573  */
574 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
575 {
576     RTMPPacket pkt;
577     uint8_t *p;
578     int ret;
579
580     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
581                                      ts, 4)) < 0)
582         return ret;
583
584     p = pkt.data;
585     bytestream_put_be32(&p, rt->bytes_read);
586     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
587                                rt->prev_pkt[1]);
588     ff_rtmp_packet_destroy(&pkt);
589
590     return ret;
591 }
592
593 //TODO: Move HMAC code somewhere. Eventually.
594 #define HMAC_IPAD_VAL 0x36
595 #define HMAC_OPAD_VAL 0x5C
596
597 /**
598  * Calculate HMAC-SHA2 digest for RTMP handshake packets.
599  *
600  * @param src    input buffer
601  * @param len    input buffer length (should be 1536)
602  * @param gap    offset in buffer where 32 bytes should not be taken into account
603  *               when calculating digest (since it will be used to store that digest)
604  * @param key    digest key
605  * @param keylen digest key length
606  * @param dst    buffer where calculated digest will be stored (32 bytes)
607  */
608 static int rtmp_calc_digest(const uint8_t *src, int len, int gap,
609                             const uint8_t *key, int keylen, uint8_t *dst)
610 {
611     struct AVSHA *sha;
612     uint8_t hmac_buf[64+32] = {0};
613     int i;
614
615     sha = av_mallocz(av_sha_size);
616     if (!sha)
617         return AVERROR(ENOMEM);
618
619     if (keylen < 64) {
620         memcpy(hmac_buf, key, keylen);
621     } else {
622         av_sha_init(sha, 256);
623         av_sha_update(sha,key, keylen);
624         av_sha_final(sha, hmac_buf);
625     }
626     for (i = 0; i < 64; i++)
627         hmac_buf[i] ^= HMAC_IPAD_VAL;
628
629     av_sha_init(sha, 256);
630     av_sha_update(sha, hmac_buf, 64);
631     if (gap <= 0) {
632         av_sha_update(sha, src, len);
633     } else { //skip 32 bytes used for storing digest
634         av_sha_update(sha, src, gap);
635         av_sha_update(sha, src + gap + 32, len - gap - 32);
636     }
637     av_sha_final(sha, hmac_buf + 64);
638
639     for (i = 0; i < 64; i++)
640         hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
641     av_sha_init(sha, 256);
642     av_sha_update(sha, hmac_buf, 64+32);
643     av_sha_final(sha, dst);
644
645     av_free(sha);
646
647     return 0;
648 }
649
650 /**
651  * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
652  * will be stored) into that packet.
653  *
654  * @param buf handshake data (1536 bytes)
655  * @return offset to the digest inside input data
656  */
657 static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
658 {
659     int i, digest_pos = 0;
660     int ret;
661
662     for (i = 8; i < 12; i++)
663         digest_pos += buf[i];
664     digest_pos = (digest_pos % 728) + 12;
665
666     ret = rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
667                            rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
668                            buf + digest_pos);
669     if (ret < 0)
670         return ret;
671
672     return digest_pos;
673 }
674
675 /**
676  * Verify that the received server response has the expected digest value.
677  *
678  * @param buf handshake data received from the server (1536 bytes)
679  * @param off position to search digest offset from
680  * @return 0 if digest is valid, digest position otherwise
681  */
682 static int rtmp_validate_digest(uint8_t *buf, int off)
683 {
684     int i, digest_pos = 0;
685     uint8_t digest[32];
686     int ret;
687
688     for (i = 0; i < 4; i++)
689         digest_pos += buf[i + off];
690     digest_pos = (digest_pos % 728) + off + 4;
691
692     ret = rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
693                            rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
694                            digest);
695     if (ret < 0)
696         return ret;
697
698     if (!memcmp(digest, buf + digest_pos, 32))
699         return digest_pos;
700     return 0;
701 }
702
703 /**
704  * Perform handshake with the server by means of exchanging pseudorandom data
705  * signed with HMAC-SHA2 digest.
706  *
707  * @return 0 if handshake succeeds, negative value otherwise
708  */
709 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
710 {
711     AVLFG rnd;
712     uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
713         3,                // unencrypted data
714         0, 0, 0, 0,       // client uptime
715         RTMP_CLIENT_VER1,
716         RTMP_CLIENT_VER2,
717         RTMP_CLIENT_VER3,
718         RTMP_CLIENT_VER4,
719     };
720     uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
721     uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
722     int i;
723     int server_pos, client_pos;
724     uint8_t digest[32];
725     int ret;
726
727     av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
728
729     av_lfg_init(&rnd, 0xDEADC0DE);
730     // generate handshake packet - 1536 bytes of pseudorandom data
731     for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
732         tosend[i] = av_lfg_get(&rnd) >> 24;
733     client_pos = rtmp_handshake_imprint_with_digest(tosend + 1);
734     if (client_pos < 0)
735         return client_pos;
736
737     if ((ret = ffurl_write(rt->stream, tosend,
738                            RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
739         av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
740         return ret;
741     }
742
743     if ((ret = ffurl_read_complete(rt->stream, serverdata,
744                                    RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
745         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
746         return ret;
747     }
748
749     if ((ret = ffurl_read_complete(rt->stream, clientdata,
750                                    RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
751         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
752         return ret;
753     }
754
755     av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
756            serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
757
758     if (rt->is_input && serverdata[5] >= 3) {
759         server_pos = rtmp_validate_digest(serverdata + 1, 772);
760         if (server_pos < 0)
761             return server_pos;
762
763         if (!server_pos) {
764             server_pos = rtmp_validate_digest(serverdata + 1, 8);
765             if (server_pos < 0)
766                 return server_pos;
767
768             if (!server_pos) {
769                 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
770                 return AVERROR(EIO);
771             }
772         }
773
774         ret = rtmp_calc_digest(tosend + 1 + client_pos, 32, 0, rtmp_server_key,
775                                sizeof(rtmp_server_key), digest);
776         if (ret < 0)
777             return ret;
778
779         ret = rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
780                                digest, 32, digest);
781         if (ret < 0)
782             return ret;
783
784         if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
785             av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
786             return AVERROR(EIO);
787         }
788
789         for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
790             tosend[i] = av_lfg_get(&rnd) >> 24;
791         ret = rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
792                                rtmp_player_key, sizeof(rtmp_player_key),
793                                digest);
794         if (ret < 0)
795             return ret;
796
797         ret = rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
798                                digest, 32,
799                                tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
800         if (ret < 0)
801             return ret;
802
803         // write reply back to the server
804         if ((ret = ffurl_write(rt->stream, tosend,
805                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
806             return ret;
807     } else {
808         if ((ret = ffurl_write(rt->stream, serverdata + 1,
809                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
810             return ret;
811     }
812
813     return 0;
814 }
815
816 /**
817  * Parse received packet and possibly perform some action depending on
818  * the packet contents.
819  * @return 0 for no errors, negative values for serious errors which prevent
820  *         further communications, positive values for uncritical errors
821  */
822 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
823 {
824     int i, t;
825     const uint8_t *data_end = pkt->data + pkt->data_size;
826     int ret;
827
828 #ifdef DEBUG
829     ff_rtmp_packet_dump(s, pkt);
830 #endif
831
832     switch (pkt->type) {
833     case RTMP_PT_CHUNK_SIZE:
834         if (pkt->data_size != 4) {
835             av_log(s, AV_LOG_ERROR,
836                    "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
837             return -1;
838         }
839         if (!rt->is_input)
840             if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->chunk_size,
841                                             rt->prev_pkt[1])) < 0)
842                 return ret;
843         rt->chunk_size = AV_RB32(pkt->data);
844         if (rt->chunk_size <= 0) {
845             av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
846             return -1;
847         }
848         av_log(s, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
849         break;
850     case RTMP_PT_PING:
851         t = AV_RB16(pkt->data);
852         if (t == 6)
853             if ((ret = gen_pong(s, rt, pkt)) < 0)
854                 return ret;
855         break;
856     case RTMP_PT_CLIENT_BW:
857         if (pkt->data_size < 4) {
858             av_log(s, AV_LOG_ERROR,
859                    "Client bandwidth report packet is less than 4 bytes long (%d)\n",
860                    pkt->data_size);
861             return -1;
862         }
863         av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
864         rt->client_report_size = AV_RB32(pkt->data) >> 1;
865         break;
866     case RTMP_PT_SERVER_BW:
867         rt->server_bw = AV_RB32(pkt->data);
868         if (rt->server_bw <= 0) {
869             av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n", rt->server_bw);
870             return AVERROR(EINVAL);
871         }
872         av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
873         break;
874     case RTMP_PT_INVOKE:
875         //TODO: check for the messages sent for wrong state?
876         if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
877             uint8_t tmpstr[256];
878
879             if (!ff_amf_get_field_value(pkt->data + 9, data_end,
880                                         "description", tmpstr, sizeof(tmpstr)))
881                 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
882             return -1;
883         } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
884             switch (rt->state) {
885             case STATE_HANDSHAKED:
886                 if (!rt->is_input) {
887                     if ((ret = gen_release_stream(s, rt)) < 0)
888                         return ret;
889                     if ((ret = gen_fcpublish_stream(s, rt)) < 0)
890                         return ret;
891                     rt->state = STATE_RELEASING;
892                 } else {
893                     if ((ret = gen_server_bw(s, rt)) < 0)
894                         return ret;
895                     rt->state = STATE_CONNECTING;
896                 }
897                 if ((ret = gen_create_stream(s, rt)) < 0)
898                     return ret;
899                 break;
900             case STATE_FCPUBLISH:
901                 rt->state = STATE_CONNECTING;
902                 break;
903             case STATE_RELEASING:
904                 rt->state = STATE_FCPUBLISH;
905                 /* hack for Wowza Media Server, it does not send result for
906                  * releaseStream and FCPublish calls */
907                 if (!pkt->data[10]) {
908                     int pkt_id = av_int2double(AV_RB64(pkt->data + 11));
909                     if (pkt_id == rt->create_stream_invoke)
910                         rt->state = STATE_CONNECTING;
911                 }
912                 if (rt->state != STATE_CONNECTING)
913                     break;
914             case STATE_CONNECTING:
915                 //extract a number from the result
916                 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
917                     av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
918                 } else {
919                     rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
920                 }
921                 if (rt->is_input) {
922                     if ((ret = gen_play(s, rt)) < 0)
923                         return ret;
924                     if ((ret = gen_buffer_time(s, rt)) < 0)
925                         return ret;
926                 } else {
927                     if ((ret = gen_publish(s, rt)) < 0)
928                         return ret;
929                 }
930                 rt->state = STATE_READY;
931                 break;
932             }
933         } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
934             const uint8_t* ptr = pkt->data + 11;
935             uint8_t tmpstr[256];
936
937             for (i = 0; i < 2; i++) {
938                 t = ff_amf_tag_size(ptr, data_end);
939                 if (t < 0)
940                     return 1;
941                 ptr += t;
942             }
943             t = ff_amf_get_field_value(ptr, data_end,
944                                        "level", tmpstr, sizeof(tmpstr));
945             if (!t && !strcmp(tmpstr, "error")) {
946                 if (!ff_amf_get_field_value(ptr, data_end,
947                                             "description", tmpstr, sizeof(tmpstr)))
948                     av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
949                 return -1;
950             }
951             t = ff_amf_get_field_value(ptr, data_end,
952                                        "code", tmpstr, sizeof(tmpstr));
953             if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
954             if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
955             if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
956             if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
957         } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
958             if ((ret = gen_check_bw(s, rt)) < 0)
959                 return ret;
960         }
961         break;
962     default:
963         av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
964         break;
965     }
966     return 0;
967 }
968
969 /**
970  * Interact with the server by receiving and sending RTMP packets until
971  * there is some significant data (media data or expected status notification).
972  *
973  * @param s          reading context
974  * @param for_header non-zero value tells function to work until it
975  * gets notification from the server that playing has been started,
976  * otherwise function will work until some media data is received (or
977  * an error happens)
978  * @return 0 for successful operation, negative value in case of error
979  */
980 static int get_packet(URLContext *s, int for_header)
981 {
982     RTMPContext *rt = s->priv_data;
983     int ret;
984     uint8_t *p;
985     const uint8_t *next;
986     uint32_t data_size;
987     uint32_t ts, cts, pts=0;
988
989     if (rt->state == STATE_STOPPED)
990         return AVERROR_EOF;
991
992     for (;;) {
993         RTMPPacket rpkt = { 0 };
994         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
995                                        rt->chunk_size, rt->prev_pkt[0])) <= 0) {
996             if (ret == 0) {
997                 return AVERROR(EAGAIN);
998             } else {
999                 return AVERROR(EIO);
1000             }
1001         }
1002         rt->bytes_read += ret;
1003         if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
1004             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
1005             if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
1006                 return ret;
1007             rt->last_bytes_read = rt->bytes_read;
1008         }
1009
1010         ret = rtmp_parse_result(s, rt, &rpkt);
1011         if (ret < 0) {//serious error in current packet
1012             ff_rtmp_packet_destroy(&rpkt);
1013             return ret;
1014         }
1015         if (rt->state == STATE_STOPPED) {
1016             ff_rtmp_packet_destroy(&rpkt);
1017             return AVERROR_EOF;
1018         }
1019         if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
1020             ff_rtmp_packet_destroy(&rpkt);
1021             return 0;
1022         }
1023         if (!rpkt.data_size || !rt->is_input) {
1024             ff_rtmp_packet_destroy(&rpkt);
1025             continue;
1026         }
1027         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
1028            (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
1029             ts = rpkt.timestamp;
1030
1031             // generate packet header and put data into buffer for FLV demuxer
1032             rt->flv_off  = 0;
1033             rt->flv_size = rpkt.data_size + 15;
1034             rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
1035             bytestream_put_byte(&p, rpkt.type);
1036             bytestream_put_be24(&p, rpkt.data_size);
1037             bytestream_put_be24(&p, ts);
1038             bytestream_put_byte(&p, ts >> 24);
1039             bytestream_put_be24(&p, 0);
1040             bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
1041             bytestream_put_be32(&p, 0);
1042             ff_rtmp_packet_destroy(&rpkt);
1043             return 0;
1044         } else if (rpkt.type == RTMP_PT_METADATA) {
1045             // we got raw FLV data, make it available for FLV demuxer
1046             rt->flv_off  = 0;
1047             rt->flv_size = rpkt.data_size;
1048             rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
1049             /* rewrite timestamps */
1050             next = rpkt.data;
1051             ts = rpkt.timestamp;
1052             while (next - rpkt.data < rpkt.data_size - 11) {
1053                 next++;
1054                 data_size = bytestream_get_be24(&next);
1055                 p=next;
1056                 cts = bytestream_get_be24(&next);
1057                 cts |= bytestream_get_byte(&next) << 24;
1058                 if (pts==0)
1059                     pts=cts;
1060                 ts += cts - pts;
1061                 pts = cts;
1062                 bytestream_put_be24(&p, ts);
1063                 bytestream_put_byte(&p, ts >> 24);
1064                 next += data_size + 3 + 4;
1065             }
1066             memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
1067             ff_rtmp_packet_destroy(&rpkt);
1068             return 0;
1069         }
1070         ff_rtmp_packet_destroy(&rpkt);
1071     }
1072 }
1073
1074 static int rtmp_close(URLContext *h)
1075 {
1076     RTMPContext *rt = h->priv_data;
1077     int ret = 0;
1078
1079     if (!rt->is_input) {
1080         rt->flv_data = NULL;
1081         if (rt->out_pkt.data_size)
1082             ff_rtmp_packet_destroy(&rt->out_pkt);
1083         if (rt->state > STATE_FCPUBLISH)
1084             ret = gen_fcunpublish_stream(h, rt);
1085     }
1086     if (rt->state > STATE_HANDSHAKED)
1087         ret = gen_delete_stream(h, rt);
1088
1089     av_freep(&rt->flv_data);
1090     ffurl_close(rt->stream);
1091     return ret;
1092 }
1093
1094 /**
1095  * Open RTMP connection and verify that the stream can be played.
1096  *
1097  * URL syntax: rtmp://server[:port][/app][/playpath]
1098  *             where 'app' is first one or two directories in the path
1099  *             (e.g. /ondemand/, /flash/live/, etc.)
1100  *             and 'playpath' is a file name (the rest of the path,
1101  *             may be prefixed with "mp4:")
1102  */
1103 static int rtmp_open(URLContext *s, const char *uri, int flags)
1104 {
1105     RTMPContext *rt = s->priv_data;
1106     char proto[8], hostname[256], path[1024], *fname;
1107     char *old_app;
1108     uint8_t buf[2048];
1109     int port;
1110     int ret;
1111
1112     rt->is_input = !(flags & AVIO_FLAG_WRITE);
1113
1114     av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
1115                  path, sizeof(path), s->filename);
1116
1117     if (!strcmp(proto, "rtmpt")) {
1118         /* open the http tunneling connection */
1119         ff_url_join(buf, sizeof(buf), "rtmphttp", NULL, hostname, port, NULL);
1120     } else {
1121         /* open the tcp connection */
1122         if (port < 0)
1123             port = RTMP_DEFAULT_PORT;
1124         ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
1125     }
1126
1127     if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
1128                           &s->interrupt_callback, NULL)) < 0) {
1129         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
1130         goto fail;
1131     }
1132
1133     rt->state = STATE_START;
1134     if ((ret = rtmp_handshake(s, rt)) < 0)
1135         goto fail;
1136
1137     rt->chunk_size = 128;
1138     rt->state = STATE_HANDSHAKED;
1139
1140     // Keep the application name when it has been defined by the user.
1141     old_app = rt->app;
1142
1143     rt->app = av_malloc(APP_MAX_LENGTH);
1144     if (!rt->app) {
1145         ret = AVERROR(ENOMEM);
1146         goto fail;
1147     }
1148
1149     //extract "app" part from path
1150     if (!strncmp(path, "/ondemand/", 10)) {
1151         fname = path + 10;
1152         memcpy(rt->app, "ondemand", 9);
1153     } else {
1154         char *next = *path ? path + 1 : path;
1155         char *p = strchr(next, '/');
1156         if (!p) {
1157             fname = next;
1158             rt->app[0] = '\0';
1159         } else {
1160             // make sure we do not mismatch a playpath for an application instance
1161             char *c = strchr(p + 1, ':');
1162             fname = strchr(p + 1, '/');
1163             if (!fname || (c && c < fname)) {
1164                 fname = p + 1;
1165                 av_strlcpy(rt->app, path + 1, p - path);
1166             } else {
1167                 fname++;
1168                 av_strlcpy(rt->app, path + 1, fname - path - 1);
1169             }
1170         }
1171     }
1172
1173     if (old_app) {
1174         // The name of application has been defined by the user, override it.
1175         av_free(rt->app);
1176         rt->app = old_app;
1177     }
1178
1179     if (!rt->playpath) {
1180         int len = strlen(fname);
1181
1182         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
1183         if (!rt->playpath) {
1184             ret = AVERROR(ENOMEM);
1185             goto fail;
1186         }
1187
1188         if (!strchr(fname, ':') && len >= 4 &&
1189             (!strcmp(fname + len - 4, ".f4v") ||
1190              !strcmp(fname + len - 4, ".mp4"))) {
1191             memcpy(rt->playpath, "mp4:", 5);
1192         } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
1193             fname[len - 4] = '\0';
1194         } else {
1195             rt->playpath[0] = 0;
1196         }
1197         strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5);
1198     }
1199
1200     if (!rt->tcurl) {
1201         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
1202         if (!rt->tcurl) {
1203             ret = AVERROR(ENOMEM);
1204             goto fail;
1205         }
1206         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
1207                     port, "/%s", rt->app);
1208     }
1209
1210     if (!rt->flashver) {
1211         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
1212         if (!rt->flashver) {
1213             ret = AVERROR(ENOMEM);
1214             goto fail;
1215         }
1216         if (rt->is_input) {
1217             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
1218                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
1219                     RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
1220         } else {
1221             snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
1222                     "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
1223         }
1224     }
1225
1226     rt->client_report_size = 1048576;
1227     rt->bytes_read = 0;
1228     rt->last_bytes_read = 0;
1229     rt->server_bw = 2500000;
1230
1231     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
1232            proto, path, rt->app, rt->playpath);
1233     if ((ret = gen_connect(s, rt)) < 0)
1234         goto fail;
1235
1236     do {
1237         ret = get_packet(s, 1);
1238     } while (ret == EAGAIN);
1239     if (ret < 0)
1240         goto fail;
1241
1242     if (rt->is_input) {
1243         // generate FLV header for demuxer
1244         rt->flv_size = 13;
1245         rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
1246         rt->flv_off  = 0;
1247         memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
1248     } else {
1249         rt->flv_size = 0;
1250         rt->flv_data = NULL;
1251         rt->flv_off  = 0;
1252         rt->skip_bytes = 13;
1253     }
1254
1255     s->max_packet_size = rt->stream->max_packet_size;
1256     s->is_streamed     = 1;
1257     return 0;
1258
1259 fail:
1260     rtmp_close(s);
1261     return ret;
1262 }
1263
1264 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
1265 {
1266     RTMPContext *rt = s->priv_data;
1267     int orig_size = size;
1268     int ret;
1269
1270     while (size > 0) {
1271         int data_left = rt->flv_size - rt->flv_off;
1272
1273         if (data_left >= size) {
1274             memcpy(buf, rt->flv_data + rt->flv_off, size);
1275             rt->flv_off += size;
1276             return orig_size;
1277         }
1278         if (data_left > 0) {
1279             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
1280             buf  += data_left;
1281             size -= data_left;
1282             rt->flv_off = rt->flv_size;
1283             return data_left;
1284         }
1285         if ((ret = get_packet(s, 0)) < 0)
1286            return ret;
1287     }
1288     return orig_size;
1289 }
1290
1291 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
1292 {
1293     RTMPContext *rt = s->priv_data;
1294     int size_temp = size;
1295     int pktsize, pkttype;
1296     uint32_t ts;
1297     const uint8_t *buf_temp = buf;
1298     uint8_t c;
1299     int ret;
1300
1301     do {
1302         if (rt->skip_bytes) {
1303             int skip = FFMIN(rt->skip_bytes, size_temp);
1304             buf_temp       += skip;
1305             size_temp      -= skip;
1306             rt->skip_bytes -= skip;
1307             continue;
1308         }
1309
1310         if (rt->flv_header_bytes < 11) {
1311             const uint8_t *header = rt->flv_header;
1312             int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
1313             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
1314             rt->flv_header_bytes += copy;
1315             size_temp            -= copy;
1316             if (rt->flv_header_bytes < 11)
1317                 break;
1318
1319             pkttype = bytestream_get_byte(&header);
1320             pktsize = bytestream_get_be24(&header);
1321             ts = bytestream_get_be24(&header);
1322             ts |= bytestream_get_byte(&header) << 24;
1323             bytestream_get_be24(&header);
1324             rt->flv_size = pktsize;
1325
1326             //force 12bytes header
1327             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
1328                 pkttype == RTMP_PT_NOTIFY) {
1329                 if (pkttype == RTMP_PT_NOTIFY)
1330                     pktsize += 16;
1331                 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
1332             }
1333
1334             //this can be a big packet, it's better to send it right here
1335             if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
1336                                              pkttype, ts, pktsize)) < 0)
1337                 return ret;
1338
1339             rt->out_pkt.extra = rt->main_channel_id;
1340             rt->flv_data = rt->out_pkt.data;
1341
1342             if (pkttype == RTMP_PT_NOTIFY)
1343                 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
1344         }
1345
1346         if (rt->flv_size - rt->flv_off > size_temp) {
1347             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
1348             rt->flv_off += size_temp;
1349             size_temp = 0;
1350         } else {
1351             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
1352             size_temp   -= rt->flv_size - rt->flv_off;
1353             rt->flv_off += rt->flv_size - rt->flv_off;
1354         }
1355
1356         if (rt->flv_off == rt->flv_size) {
1357             rt->skip_bytes = 4;
1358
1359             if ((ret = ff_rtmp_packet_write(rt->stream, &rt->out_pkt,
1360                                             rt->chunk_size, rt->prev_pkt[1])) < 0)
1361                 return ret;
1362             ff_rtmp_packet_destroy(&rt->out_pkt);
1363             rt->flv_size = 0;
1364             rt->flv_off = 0;
1365             rt->flv_header_bytes = 0;
1366             rt->flv_nb_packets++;
1367         }
1368     } while (buf_temp - buf < size);
1369
1370     if (rt->flv_nb_packets < rt->flush_interval)
1371         return size;
1372     rt->flv_nb_packets = 0;
1373
1374     /* set stream into nonblocking mode */
1375     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
1376
1377     /* try to read one byte from the stream */
1378     ret = ffurl_read(rt->stream, &c, 1);
1379
1380     /* switch the stream back into blocking mode */
1381     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
1382
1383     if (ret == AVERROR(EAGAIN)) {
1384         /* no incoming data to handle */
1385         return size;
1386     } else if (ret < 0) {
1387         return ret;
1388     } else if (ret == 1) {
1389         RTMPPacket rpkt = { 0 };
1390
1391         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
1392                                                 rt->chunk_size,
1393                                                 rt->prev_pkt[0], c)) <= 0)
1394              return ret;
1395
1396         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
1397             return ret;
1398
1399         ff_rtmp_packet_destroy(&rpkt);
1400     }
1401
1402     return size;
1403 }
1404
1405 #define OFFSET(x) offsetof(RTMPContext, x)
1406 #define DEC AV_OPT_FLAG_DECODING_PARAM
1407 #define ENC AV_OPT_FLAG_ENCODING_PARAM
1408
1409 static const AVOption rtmp_options[] = {
1410     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1411     {"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},
1412     {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1413     {"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},
1414     {"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},
1415     {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
1416     {"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
1417     {"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
1418     {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"},
1419     {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1420     {"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},
1421     {"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},
1422     { NULL },
1423 };
1424
1425 static const AVClass rtmp_class = {
1426     .class_name = "rtmp",
1427     .item_name  = av_default_item_name,
1428     .option     = rtmp_options,
1429     .version    = LIBAVUTIL_VERSION_INT,
1430 };
1431
1432 URLProtocol ff_rtmp_protocol = {
1433     .name           = "rtmp",
1434     .url_open       = rtmp_open,
1435     .url_read       = rtmp_read,
1436     .url_write      = rtmp_write,
1437     .url_close      = rtmp_close,
1438     .priv_data_size = sizeof(RTMPContext),
1439     .flags          = URL_PROTOCOL_FLAG_NETWORK,
1440     .priv_data_class= &rtmp_class,
1441 };
1442
1443 static const AVClass rtmpt_class = {
1444     .class_name = "rtmpt",
1445     .item_name  = av_default_item_name,
1446     .option     = rtmp_options,
1447     .version    = LIBAVUTIL_VERSION_INT,
1448 };
1449
1450 URLProtocol ff_rtmpt_protocol = {
1451     .name            = "rtmpt",
1452     .url_open        = rtmp_open,
1453     .url_read        = rtmp_read,
1454     .url_write       = rtmp_write,
1455     .url_close       = rtmp_close,
1456     .priv_data_size  = sizeof(RTMPContext),
1457     .flags           = URL_PROTOCOL_FLAG_NETWORK,
1458     .priv_data_class = &rtmpt_class,
1459 };