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