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