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