rtmpproto.c
Go to the documentation of this file.
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/base64.h"
30 #include "libavutil/intfloat.h"
31 #include "libavutil/lfg.h"
32 #include "libavutil/md5.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/random_seed.h"
35 #include "libavutil/sha.h"
36 #include "avformat.h"
37 #include "internal.h"
38 
39 #include "network.h"
40 
41 #include "flv.h"
42 #include "rtmp.h"
43 #include "rtmpcrypt.h"
44 #include "rtmppkt.h"
45 #include "url.h"
46 
47 #if CONFIG_ZLIB
48 #include <zlib.h>
49 #endif
50 
51 //#define DEBUG
52 
53 #define APP_MAX_LENGTH 1024
54 #define PLAYPATH_MAX_LENGTH 256
55 #define TCURL_MAX_LENGTH 512
56 #define FLASHVER_MAX_LENGTH 64
57 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
58 
59 /** RTMP protocol handler state */
60 typedef enum {
61  STATE_START, ///< client has not done anything yet
62  STATE_HANDSHAKED, ///< client has performed handshake
63  STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
64  STATE_PLAYING, ///< client has started receiving multimedia data from server
65  STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
66  STATE_RECEIVING, ///< received a publish command (for input)
67  STATE_STOPPED, ///< the broadcast has been stopped
68 } ClientState;
69 
70 typedef struct TrackedMethod {
71  char *name;
72  int id;
74 
75 /** protocol handler context */
76 typedef struct RTMPContext {
77  const AVClass *class;
78  URLContext* stream; ///< TCP stream used in interactions with RTMP server
79  RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
80  int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
81  int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
82  int is_input; ///< input/output flag
83  char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
84  int live; ///< 0: recorded, -1: live, -2: both
85  char *app; ///< name of application
86  char *conn; ///< append arbitrary AMF data to the Connect message
87  ClientState state; ///< current state
88  int main_channel_id; ///< an additional channel ID which is used for some invocations
89  uint8_t* flv_data; ///< buffer with data for demuxer
90  int flv_size; ///< current buffer size
91  int flv_off; ///< number of bytes read from current buffer
92  int flv_nb_packets; ///< number of flv packets published
93  RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
94  uint32_t client_report_size; ///< number of bytes after which client should report to server
95  uint32_t bytes_read; ///< number of bytes read from server
96  uint32_t last_bytes_read; ///< number of bytes read last reported to server
97  int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
98  uint8_t flv_header[11]; ///< partial incoming flv packet header
99  int flv_header_bytes; ///< number of initialized bytes in flv_header
100  int nb_invokes; ///< keeps track of invoke messages
101  char* tcurl; ///< url of the target stream
102  char* flashver; ///< version of the flash plugin
103  char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
104  int swfhash_len; ///< length of the SHA256 hash
105  int swfsize; ///< size of the decompressed SWF file
106  char* swfurl; ///< url of the swf player
107  char* swfverify; ///< URL to player swf file, compute hash/size automatically
108  char swfverification[42]; ///< hash of the SWF verification
109  char* pageurl; ///< url of the web page
110  char* subscribe; ///< name of live stream to subscribe
111  int server_bw; ///< server bandwidth
112  int client_buffer_time; ///< client buffer time in ms
113  int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
114  int encrypted; ///< use an encrypted connection (RTMPE only)
115  TrackedMethod*tracked_methods; ///< tracked methods buffer
116  int nb_tracked_methods; ///< number of tracked methods
117  int tracked_methods_size; ///< size of the tracked methods buffer
118  int listen; ///< listen mode flag
119  int listen_timeout; ///< listen timeout to wait for new connections
120  int nb_streamid; ///< The next stream id to return on createStream calls
121  char username[50];
122  char password[50];
123  char auth_params[500];
126 } RTMPContext;
127 
128 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
129 /** Client key used for digest signing */
130 static const uint8_t rtmp_player_key[] = {
131  'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
132  'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
133 
134  0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
135  0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
136  0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
137 };
138 
139 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
140 /** Key used for RTMP server digest signing */
141 static const uint8_t rtmp_server_key[] = {
142  'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
143  'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
144  'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
145 
146  0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
147  0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
148  0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
149 };
150 
151 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
152 {
153  void *ptr;
154 
155  if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
156  rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
157  ptr = av_realloc(rt->tracked_methods,
158  rt->tracked_methods_size * sizeof(*rt->tracked_methods));
159  if (!ptr)
160  return AVERROR(ENOMEM);
161  rt->tracked_methods = ptr;
162  }
163 
166  return AVERROR(ENOMEM);
168  rt->nb_tracked_methods++;
169 
170  return 0;
171 }
172 
173 static void del_tracked_method(RTMPContext *rt, int index)
174 {
175  memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
176  sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
177  rt->nb_tracked_methods--;
178 }
179 
181  char **tracked_method)
182 {
183  RTMPContext *rt = s->priv_data;
184  GetByteContext gbc;
185  double pkt_id;
186  int ret;
187  int i;
188 
189  bytestream2_init(&gbc, pkt->data + offset, pkt->data_size - offset);
190  if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
191  return ret;
192 
193  for (i = 0; i < rt->nb_tracked_methods; i++) {
194  if (rt->tracked_methods[i].id != pkt_id)
195  continue;
196 
197  *tracked_method = rt->tracked_methods[i].name;
198  del_tracked_method(rt, i);
199  break;
200  }
201 
202  return 0;
203 }
204 
206 {
207  int i;
208 
209  for (i = 0; i < rt->nb_tracked_methods; i ++)
210  av_free(rt->tracked_methods[i].name);
212  rt->tracked_methods = NULL;
213  rt->tracked_methods_size = 0;
214  rt->nb_tracked_methods = 0;
215 }
216 
218 {
219  int ret;
220 
221  if (pkt->type == RTMP_PT_INVOKE && track) {
222  GetByteContext gbc;
223  char name[128];
224  double pkt_id;
225  int len;
226 
227  bytestream2_init(&gbc, pkt->data, pkt->data_size);
228  if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
229  goto fail;
230 
231  if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
232  goto fail;
233 
234  if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
235  goto fail;
236  }
237 
238  ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
239  rt->prev_pkt[1]);
240 fail:
242  return ret;
243 }
244 
245 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
246 {
247  char *field, *value;
248  char type;
249 
250  /* The type must be B for Boolean, N for number, S for string, O for
251  * object, or Z for null. For Booleans the data must be either 0 or 1 for
252  * FALSE or TRUE, respectively. Likewise for Objects the data must be
253  * 0 or 1 to end or begin an object, respectively. Data items in subobjects
254  * may be named, by prefixing the type with 'N' and specifying the name
255  * before the value (ie. NB:myFlag:1). This option may be used multiple times
256  * to construct arbitrary AMF sequences. */
257  if (param[0] && param[1] == ':') {
258  type = param[0];
259  value = param + 2;
260  } else if (param[0] == 'N' && param[1] && param[2] == ':') {
261  type = param[1];
262  field = param + 3;
263  value = strchr(field, ':');
264  if (!value)
265  goto fail;
266  *value = '\0';
267  value++;
268 
269  ff_amf_write_field_name(p, field);
270  } else {
271  goto fail;
272  }
273 
274  switch (type) {
275  case 'B':
276  ff_amf_write_bool(p, value[0] != '0');
277  break;
278  case 'S':
279  ff_amf_write_string(p, value);
280  break;
281  case 'N':
282  ff_amf_write_number(p, strtod(value, NULL));
283  break;
284  case 'Z':
286  break;
287  case 'O':
288  if (value[0] != '0')
290  else
292  break;
293  default:
294  goto fail;
295  break;
296  }
297 
298  return 0;
299 
300 fail:
301  av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
302  return AVERROR(EINVAL);
303 }
304 
305 /**
306  * Generate 'connect' call and send it to the server.
307  */
309 {
310  RTMPPacket pkt;
311  uint8_t *p;
312  int ret;
313 
315  0, 4096 + APP_MAX_LENGTH)) < 0)
316  return ret;
317 
318  p = pkt.data;
319 
320  ff_amf_write_string(&p, "connect");
321  ff_amf_write_number(&p, ++rt->nb_invokes);
323  ff_amf_write_field_name(&p, "app");
324  ff_amf_write_string2(&p, rt->app, rt->auth_params);
325 
326  if (!rt->is_input) {
327  ff_amf_write_field_name(&p, "type");
328  ff_amf_write_string(&p, "nonprivate");
329  }
330  ff_amf_write_field_name(&p, "flashVer");
331  ff_amf_write_string(&p, rt->flashver);
332 
333  if (rt->swfurl) {
334  ff_amf_write_field_name(&p, "swfUrl");
335  ff_amf_write_string(&p, rt->swfurl);
336  }
337 
338  ff_amf_write_field_name(&p, "tcUrl");
339  ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
340  if (rt->is_input) {
341  ff_amf_write_field_name(&p, "fpad");
342  ff_amf_write_bool(&p, 0);
343  ff_amf_write_field_name(&p, "capabilities");
344  ff_amf_write_number(&p, 15.0);
345 
346  /* Tell the server we support all the audio codecs except
347  * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
348  * which are unused in the RTMP protocol implementation. */
349  ff_amf_write_field_name(&p, "audioCodecs");
350  ff_amf_write_number(&p, 4071.0);
351  ff_amf_write_field_name(&p, "videoCodecs");
352  ff_amf_write_number(&p, 252.0);
353  ff_amf_write_field_name(&p, "videoFunction");
354  ff_amf_write_number(&p, 1.0);
355 
356  if (rt->pageurl) {
357  ff_amf_write_field_name(&p, "pageUrl");
358  ff_amf_write_string(&p, rt->pageurl);
359  }
360  }
362 
363  if (rt->conn) {
364  char *param = rt->conn;
365 
366  // Write arbitrary AMF data to the Connect message.
367  while (param != NULL) {
368  char *sep;
369  param += strspn(param, " ");
370  if (!*param)
371  break;
372  sep = strchr(param, ' ');
373  if (sep)
374  *sep = '\0';
375  if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
376  // Invalid AMF parameter.
378  return ret;
379  }
380 
381  if (sep)
382  param = sep + 1;
383  else
384  break;
385  }
386  }
387 
388  pkt.data_size = p - pkt.data;
389 
390  return rtmp_send_packet(rt, &pkt, 1);
391 }
392 
394 {
395  RTMPPacket pkt = { 0 };
396  uint8_t *p;
397  const uint8_t *cp;
398  int ret;
399  char command[64];
400  int stringlen;
401  double seqnum;
402  uint8_t tmpstr[256];
403  GetByteContext gbc;
404 
405  if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
406  rt->prev_pkt[1])) < 0)
407  return ret;
408  cp = pkt.data;
409  bytestream2_init(&gbc, cp, pkt.data_size);
410  if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
411  av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
413  return AVERROR_INVALIDDATA;
414  }
415  if (strcmp(command, "connect")) {
416  av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
418  return AVERROR_INVALIDDATA;
419  }
420  ret = ff_amf_read_number(&gbc, &seqnum);
421  if (ret)
422  av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
423  /* Here one could parse an AMF Object with data as flashVers and others. */
424  ret = ff_amf_get_field_value(gbc.buffer,
426  "app", tmpstr, sizeof(tmpstr));
427  if (ret)
428  av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
429  if (!ret && strcmp(tmpstr, rt->app))
430  av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
431  tmpstr, rt->app);
433 
434  // Send Window Acknowledgement Size (as defined in speficication)
436  RTMP_PT_SERVER_BW, 0, 4)) < 0)
437  return ret;
438  p = pkt.data;
439  bytestream_put_be32(&p, rt->server_bw);
440  pkt.data_size = p - pkt.data;
441  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
442  rt->prev_pkt[1]);
444  if (ret < 0)
445  return ret;
446  // Send Peer Bandwidth
448  RTMP_PT_CLIENT_BW, 0, 5)) < 0)
449  return ret;
450  p = pkt.data;
451  bytestream_put_be32(&p, rt->server_bw);
452  bytestream_put_byte(&p, 2); // dynamic
453  pkt.data_size = p - pkt.data;
454  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
455  rt->prev_pkt[1]);
457  if (ret < 0)
458  return ret;
459 
460  // Ping request
462  RTMP_PT_PING, 0, 6)) < 0)
463  return ret;
464 
465  p = pkt.data;
466  bytestream_put_be16(&p, 0); // 0 -> Stream Begin
467  bytestream_put_be32(&p, 0);
468  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
469  rt->prev_pkt[1]);
471  if (ret < 0)
472  return ret;
473 
474  // Chunk size
476  RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
477  return ret;
478 
479  p = pkt.data;
480  bytestream_put_be32(&p, rt->out_chunk_size);
481  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
482  rt->prev_pkt[1]);
484  if (ret < 0)
485  return ret;
486 
487  // Send result_ NetConnection.Connect.Success to connect
489  RTMP_PT_INVOKE, 0,
491  return ret;
492 
493  p = pkt.data;
494  ff_amf_write_string(&p, "_result");
495  ff_amf_write_number(&p, seqnum);
496 
498  ff_amf_write_field_name(&p, "fmsVer");
499  ff_amf_write_string(&p, "FMS/3,0,1,123");
500  ff_amf_write_field_name(&p, "capabilities");
501  ff_amf_write_number(&p, 31);
503 
505  ff_amf_write_field_name(&p, "level");
506  ff_amf_write_string(&p, "status");
507  ff_amf_write_field_name(&p, "code");
508  ff_amf_write_string(&p, "NetConnection.Connect.Success");
509  ff_amf_write_field_name(&p, "description");
510  ff_amf_write_string(&p, "Connection succeeded.");
511  ff_amf_write_field_name(&p, "objectEncoding");
512  ff_amf_write_number(&p, 0);
514 
515  pkt.data_size = p - pkt.data;
516  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
517  rt->prev_pkt[1]);
519  if (ret < 0)
520  return ret;
521 
523  RTMP_PT_INVOKE, 0, 30)) < 0)
524  return ret;
525  p = pkt.data;
526  ff_amf_write_string(&p, "onBWDone");
527  ff_amf_write_number(&p, 0);
528  ff_amf_write_null(&p);
529  ff_amf_write_number(&p, 8192);
530  pkt.data_size = p - pkt.data;
531  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
532  rt->prev_pkt[1]);
534 
535  return ret;
536 }
537 
538 /**
539  * Generate 'releaseStream' call and send it to the server. It should make
540  * the server release some channel for media streams.
541  */
543 {
544  RTMPPacket pkt;
545  uint8_t *p;
546  int ret;
547 
549  0, 29 + strlen(rt->playpath))) < 0)
550  return ret;
551 
552  av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
553  p = pkt.data;
554  ff_amf_write_string(&p, "releaseStream");
555  ff_amf_write_number(&p, ++rt->nb_invokes);
556  ff_amf_write_null(&p);
557  ff_amf_write_string(&p, rt->playpath);
558 
559  return rtmp_send_packet(rt, &pkt, 1);
560 }
561 
562 /**
563  * Generate 'FCPublish' call and send it to the server. It should make
564  * the server preapare for receiving media streams.
565  */
567 {
568  RTMPPacket pkt;
569  uint8_t *p;
570  int ret;
571 
573  0, 25 + strlen(rt->playpath))) < 0)
574  return ret;
575 
576  av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
577  p = pkt.data;
578  ff_amf_write_string(&p, "FCPublish");
579  ff_amf_write_number(&p, ++rt->nb_invokes);
580  ff_amf_write_null(&p);
581  ff_amf_write_string(&p, rt->playpath);
582 
583  return rtmp_send_packet(rt, &pkt, 1);
584 }
585 
586 /**
587  * Generate 'FCUnpublish' call and send it to the server. It should make
588  * the server destroy stream.
589  */
591 {
592  RTMPPacket pkt;
593  uint8_t *p;
594  int ret;
595 
597  0, 27 + strlen(rt->playpath))) < 0)
598  return ret;
599 
600  av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
601  p = pkt.data;
602  ff_amf_write_string(&p, "FCUnpublish");
603  ff_amf_write_number(&p, ++rt->nb_invokes);
604  ff_amf_write_null(&p);
605  ff_amf_write_string(&p, rt->playpath);
606 
607  return rtmp_send_packet(rt, &pkt, 0);
608 }
609 
610 /**
611  * Generate 'createStream' call and send it to the server. It should make
612  * the server allocate some channel for media streams.
613  */
615 {
616  RTMPPacket pkt;
617  uint8_t *p;
618  int ret;
619 
620  av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
621 
623  0, 25)) < 0)
624  return ret;
625 
626  p = pkt.data;
627  ff_amf_write_string(&p, "createStream");
628  ff_amf_write_number(&p, ++rt->nb_invokes);
629  ff_amf_write_null(&p);
630 
631  return rtmp_send_packet(rt, &pkt, 1);
632 }
633 
634 
635 /**
636  * Generate 'deleteStream' call and send it to the server. It should make
637  * the server remove some channel for media streams.
638  */
640 {
641  RTMPPacket pkt;
642  uint8_t *p;
643  int ret;
644 
645  av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
646 
648  0, 34)) < 0)
649  return ret;
650 
651  p = pkt.data;
652  ff_amf_write_string(&p, "deleteStream");
653  ff_amf_write_number(&p, ++rt->nb_invokes);
654  ff_amf_write_null(&p);
656 
657  return rtmp_send_packet(rt, &pkt, 0);
658 }
659 
660 /**
661  * Generate client buffer time and send it to the server.
662  */
664 {
665  RTMPPacket pkt;
666  uint8_t *p;
667  int ret;
668 
670  1, 10)) < 0)
671  return ret;
672 
673  p = pkt.data;
674  bytestream_put_be16(&p, 3);
675  bytestream_put_be32(&p, rt->main_channel_id);
676  bytestream_put_be32(&p, rt->client_buffer_time);
677 
678  return rtmp_send_packet(rt, &pkt, 0);
679 }
680 
681 /**
682  * Generate 'play' call and send it to the server, then ping the server
683  * to start actual playing.
684  */
685 static int gen_play(URLContext *s, RTMPContext *rt)
686 {
687  RTMPPacket pkt;
688  uint8_t *p;
689  int ret;
690 
691  av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
692 
694  0, 29 + strlen(rt->playpath))) < 0)
695  return ret;
696 
697  pkt.extra = rt->main_channel_id;
698 
699  p = pkt.data;
700  ff_amf_write_string(&p, "play");
701  ff_amf_write_number(&p, ++rt->nb_invokes);
702  ff_amf_write_null(&p);
703  ff_amf_write_string(&p, rt->playpath);
704  ff_amf_write_number(&p, rt->live);
705 
706  return rtmp_send_packet(rt, &pkt, 1);
707 }
708 
709 /**
710  * Generate 'publish' call and send it to the server.
711  */
713 {
714  RTMPPacket pkt;
715  uint8_t *p;
716  int ret;
717 
718  av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
719 
721  0, 30 + strlen(rt->playpath))) < 0)
722  return ret;
723 
724  pkt.extra = rt->main_channel_id;
725 
726  p = pkt.data;
727  ff_amf_write_string(&p, "publish");
728  ff_amf_write_number(&p, ++rt->nb_invokes);
729  ff_amf_write_null(&p);
730  ff_amf_write_string(&p, rt->playpath);
731  ff_amf_write_string(&p, "live");
732 
733  return rtmp_send_packet(rt, &pkt, 1);
734 }
735 
736 /**
737  * Generate ping reply and send it to the server.
738  */
739 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
740 {
741  RTMPPacket pkt;
742  uint8_t *p;
743  int ret;
744 
745  if (ppkt->data_size < 6) {
746  av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
747  ppkt->data_size);
748  return AVERROR_INVALIDDATA;
749  }
750 
752  ppkt->timestamp + 1, 6)) < 0)
753  return ret;
754 
755  p = pkt.data;
756  bytestream_put_be16(&p, 7);
757  bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
758 
759  return rtmp_send_packet(rt, &pkt, 0);
760 }
761 
762 /**
763  * Generate SWF verification message and send it to the server.
764  */
766 {
767  RTMPPacket pkt;
768  uint8_t *p;
769  int ret;
770 
771  av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
773  0, 44)) < 0)
774  return ret;
775 
776  p = pkt.data;
777  bytestream_put_be16(&p, 27);
778  memcpy(p, rt->swfverification, 42);
779 
780  return rtmp_send_packet(rt, &pkt, 0);
781 }
782 
783 /**
784  * Generate server bandwidth message and send it to the server.
785  */
787 {
788  RTMPPacket pkt;
789  uint8_t *p;
790  int ret;
791 
793  0, 4)) < 0)
794  return ret;
795 
796  p = pkt.data;
797  bytestream_put_be32(&p, rt->server_bw);
798 
799  return rtmp_send_packet(rt, &pkt, 0);
800 }
801 
802 /**
803  * Generate check bandwidth message and send it to the server.
804  */
806 {
807  RTMPPacket pkt;
808  uint8_t *p;
809  int ret;
810 
812  0, 21)) < 0)
813  return ret;
814 
815  p = pkt.data;
816  ff_amf_write_string(&p, "_checkbw");
817  ff_amf_write_number(&p, ++rt->nb_invokes);
818  ff_amf_write_null(&p);
819 
820  return rtmp_send_packet(rt, &pkt, 1);
821 }
822 
823 /**
824  * Generate report on bytes read so far and send it to the server.
825  */
826 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
827 {
828  RTMPPacket pkt;
829  uint8_t *p;
830  int ret;
831 
833  ts, 4)) < 0)
834  return ret;
835 
836  p = pkt.data;
837  bytestream_put_be32(&p, rt->bytes_read);
838 
839  return rtmp_send_packet(rt, &pkt, 0);
840 }
841 
843  const char *subscribe)
844 {
845  RTMPPacket pkt;
846  uint8_t *p;
847  int ret;
848 
850  0, 27 + strlen(subscribe))) < 0)
851  return ret;
852 
853  p = pkt.data;
854  ff_amf_write_string(&p, "FCSubscribe");
855  ff_amf_write_number(&p, ++rt->nb_invokes);
856  ff_amf_write_null(&p);
857  ff_amf_write_string(&p, subscribe);
858 
859  return rtmp_send_packet(rt, &pkt, 1);
860 }
861 
862 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
863  const uint8_t *key, int keylen, uint8_t *dst)
864 {
865  struct AVSHA *sha;
866  uint8_t hmac_buf[64+32] = {0};
867  int i;
868 
869  sha = av_sha_alloc();
870  if (!sha)
871  return AVERROR(ENOMEM);
872 
873  if (keylen < 64) {
874  memcpy(hmac_buf, key, keylen);
875  } else {
876  av_sha_init(sha, 256);
877  av_sha_update(sha,key, keylen);
878  av_sha_final(sha, hmac_buf);
879  }
880  for (i = 0; i < 64; i++)
881  hmac_buf[i] ^= HMAC_IPAD_VAL;
882 
883  av_sha_init(sha, 256);
884  av_sha_update(sha, hmac_buf, 64);
885  if (gap <= 0) {
886  av_sha_update(sha, src, len);
887  } else { //skip 32 bytes used for storing digest
888  av_sha_update(sha, src, gap);
889  av_sha_update(sha, src + gap + 32, len - gap - 32);
890  }
891  av_sha_final(sha, hmac_buf + 64);
892 
893  for (i = 0; i < 64; i++)
894  hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
895  av_sha_init(sha, 256);
896  av_sha_update(sha, hmac_buf, 64+32);
897  av_sha_final(sha, dst);
898 
899  av_free(sha);
900 
901  return 0;
902 }
903 
904 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
905  int add_val)
906 {
907  int i, digest_pos = 0;
908 
909  for (i = 0; i < 4; i++)
910  digest_pos += buf[i + off];
911  digest_pos = digest_pos % mod_val + add_val;
912 
913  return digest_pos;
914 }
915 
916 /**
917  * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
918  * will be stored) into that packet.
919  *
920  * @param buf handshake data (1536 bytes)
921  * @param encrypted use an encrypted connection (RTMPE)
922  * @return offset to the digest inside input data
923  */
924 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
925 {
926  int ret, digest_pos;
927 
928  if (encrypted)
929  digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
930  else
931  digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
932 
933  ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
935  buf + digest_pos);
936  if (ret < 0)
937  return ret;
938 
939  return digest_pos;
940 }
941 
942 /**
943  * Verify that the received server response has the expected digest value.
944  *
945  * @param buf handshake data received from the server (1536 bytes)
946  * @param off position to search digest offset from
947  * @return 0 if digest is valid, digest position otherwise
948  */
950 {
951  uint8_t digest[32];
952  int ret, digest_pos;
953 
954  digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
955 
956  ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
958  digest);
959  if (ret < 0)
960  return ret;
961 
962  if (!memcmp(digest, buf + digest_pos, 32))
963  return digest_pos;
964  return 0;
965 }
966 
968  uint8_t *buf)
969 {
970  uint8_t *p;
971  int ret;
972 
973  if (rt->swfhash_len != 32) {
974  av_log(s, AV_LOG_ERROR,
975  "Hash of the decompressed SWF file is not 32 bytes long.\n");
976  return AVERROR(EINVAL);
977  }
978 
979  p = &rt->swfverification[0];
980  bytestream_put_byte(&p, 1);
981  bytestream_put_byte(&p, 1);
982  bytestream_put_be32(&p, rt->swfsize);
983  bytestream_put_be32(&p, rt->swfsize);
984 
985  if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
986  return ret;
987 
988  return 0;
989 }
990 
991 #if CONFIG_ZLIB
992 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
993  uint8_t **out_data, int64_t *out_size)
994 {
995  z_stream zs = { 0 };
996  void *ptr;
997  int size;
998  int ret = 0;
999 
1000  zs.avail_in = in_size;
1001  zs.next_in = in_data;
1002  ret = inflateInit(&zs);
1003  if (ret != Z_OK)
1004  return AVERROR_UNKNOWN;
1005 
1006  do {
1007  uint8_t tmp_buf[16384];
1008 
1009  zs.avail_out = sizeof(tmp_buf);
1010  zs.next_out = tmp_buf;
1011 
1012  ret = inflate(&zs, Z_NO_FLUSH);
1013  if (ret != Z_OK && ret != Z_STREAM_END) {
1014  ret = AVERROR_UNKNOWN;
1015  goto fail;
1016  }
1017 
1018  size = sizeof(tmp_buf) - zs.avail_out;
1019  if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1020  ret = AVERROR(ENOMEM);
1021  goto fail;
1022  }
1023  *out_data = ptr;
1024 
1025  memcpy(*out_data + *out_size, tmp_buf, size);
1026  *out_size += size;
1027  } while (zs.avail_out == 0);
1028 
1029 fail:
1030  inflateEnd(&zs);
1031  return ret;
1032 }
1033 #endif
1034 
1036 {
1037  RTMPContext *rt = s->priv_data;
1038  uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1039  int64_t in_size, out_size;
1040  URLContext *stream;
1041  char swfhash[32];
1042  int swfsize;
1043  int ret = 0;
1044 
1045  /* Get the SWF player file. */
1046  if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1047  &s->interrupt_callback, NULL)) < 0) {
1048  av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1049  goto fail;
1050  }
1051 
1052  if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1053  ret = AVERROR(EIO);
1054  goto fail;
1055  }
1056 
1057  if (!(in_data = av_malloc(in_size))) {
1058  ret = AVERROR(ENOMEM);
1059  goto fail;
1060  }
1061 
1062  if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1063  goto fail;
1064 
1065  if (in_size < 3) {
1066  ret = AVERROR_INVALIDDATA;
1067  goto fail;
1068  }
1069 
1070  if (!memcmp(in_data, "CWS", 3)) {
1071  /* Decompress the SWF player file using Zlib. */
1072  if (!(out_data = av_malloc(8))) {
1073  ret = AVERROR(ENOMEM);
1074  goto fail;
1075  }
1076  *in_data = 'F'; // magic stuff
1077  memcpy(out_data, in_data, 8);
1078  out_size = 8;
1079 
1080 #if CONFIG_ZLIB
1081  if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1082  &out_data, &out_size)) < 0)
1083  goto fail;
1084 #else
1085  av_log(s, AV_LOG_ERROR,
1086  "Zlib is required for decompressing the SWF player file.\n");
1087  ret = AVERROR(EINVAL);
1088  goto fail;
1089 #endif
1090  swfsize = out_size;
1091  swfdata = out_data;
1092  } else {
1093  swfsize = in_size;
1094  swfdata = in_data;
1095  }
1096 
1097  /* Compute the SHA256 hash of the SWF player file. */
1098  if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1099  "Genuine Adobe Flash Player 001", 30,
1100  swfhash)) < 0)
1101  goto fail;
1102 
1103  /* Set SWFVerification parameters. */
1104  av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1105  rt->swfsize = swfsize;
1106 
1107 fail:
1108  av_freep(&in_data);
1109  av_freep(&out_data);
1110  ffurl_close(stream);
1111  return ret;
1112 }
1113 
1114 /**
1115  * Perform handshake with the server by means of exchanging pseudorandom data
1116  * signed with HMAC-SHA2 digest.
1117  *
1118  * @return 0 if handshake succeeds, negative value otherwise
1119  */
1121 {
1122  AVLFG rnd;
1123  uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1124  3, // unencrypted data
1125  0, 0, 0, 0, // client uptime
1130  };
1131  uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1132  uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1133  int i;
1134  int server_pos, client_pos;
1135  uint8_t digest[32], signature[32];
1136  int ret, type = 0;
1137 
1138  av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1139 
1140  av_lfg_init(&rnd, 0xDEADC0DE);
1141  // generate handshake packet - 1536 bytes of pseudorandom data
1142  for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1143  tosend[i] = av_lfg_get(&rnd) >> 24;
1144 
1146  /* When the client wants to use RTMPE, we have to change the command
1147  * byte to 0x06 which means to use encrypted data and we have to set
1148  * the flash version to at least 9.0.115.0. */
1149  tosend[0] = 6;
1150  tosend[5] = 128;
1151  tosend[6] = 0;
1152  tosend[7] = 3;
1153  tosend[8] = 2;
1154 
1155  /* Initialize the Diffie-Hellmann context and generate the public key
1156  * to send to the server. */
1157  if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1158  return ret;
1159  }
1160 
1161  client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1162  if (client_pos < 0)
1163  return client_pos;
1164 
1165  if ((ret = ffurl_write(rt->stream, tosend,
1166  RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1167  av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1168  return ret;
1169  }
1170 
1171  if ((ret = ffurl_read_complete(rt->stream, serverdata,
1172  RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1173  av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1174  return ret;
1175  }
1176 
1177  if ((ret = ffurl_read_complete(rt->stream, clientdata,
1179  av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1180  return ret;
1181  }
1182 
1183  av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1184  av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1185  serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1186 
1187  if (rt->is_input && serverdata[5] >= 3) {
1188  server_pos = rtmp_validate_digest(serverdata + 1, 772);
1189  if (server_pos < 0)
1190  return server_pos;
1191 
1192  if (!server_pos) {
1193  type = 1;
1194  server_pos = rtmp_validate_digest(serverdata + 1, 8);
1195  if (server_pos < 0)
1196  return server_pos;
1197 
1198  if (!server_pos) {
1199  av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1200  return AVERROR(EIO);
1201  }
1202  }
1203 
1204  /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1205  * key are the last 32 bytes of the server handshake. */
1206  if (rt->swfsize) {
1207  if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1208  RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1209  return ret;
1210  }
1211 
1212  ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1214  digest);
1215  if (ret < 0)
1216  return ret;
1217 
1218  ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1219  0, digest, 32, signature);
1220  if (ret < 0)
1221  return ret;
1222 
1224  /* Compute the shared secret key sent by the server and initialize
1225  * the RC4 encryption. */
1226  if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1227  tosend + 1, type)) < 0)
1228  return ret;
1229 
1230  /* Encrypt the signature received by the server. */
1231  ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1232  }
1233 
1234  if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1235  av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1236  return AVERROR(EIO);
1237  }
1238 
1239  for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1240  tosend[i] = av_lfg_get(&rnd) >> 24;
1241  ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1243  digest);
1244  if (ret < 0)
1245  return ret;
1246 
1247  ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1248  digest, 32,
1249  tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1250  if (ret < 0)
1251  return ret;
1252 
1254  /* Encrypt the signature to be send to the server. */
1255  ff_rtmpe_encrypt_sig(rt->stream, tosend +
1256  RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1257  serverdata[0]);
1258  }
1259 
1260  // write reply back to the server
1261  if ((ret = ffurl_write(rt->stream, tosend,
1262  RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1263  return ret;
1264 
1266  /* Set RC4 keys for encryption and update the keystreams. */
1267  if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1268  return ret;
1269  }
1270  } else {
1272  /* Compute the shared secret key sent by the server and initialize
1273  * the RC4 encryption. */
1274  if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1275  tosend + 1, 1)) < 0)
1276  return ret;
1277 
1278  if (serverdata[0] == 9) {
1279  /* Encrypt the signature received by the server. */
1280  ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1281  serverdata[0]);
1282  }
1283  }
1284 
1285  if ((ret = ffurl_write(rt->stream, serverdata + 1,
1287  return ret;
1288 
1290  /* Set RC4 keys for encryption and update the keystreams. */
1291  if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1292  return ret;
1293  }
1294  }
1295 
1296  return 0;
1297 }
1298 
1299 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1300  uint32_t *second_int, char *arraydata,
1301  int size)
1302 {
1303  int inoutsize;
1304 
1305  inoutsize = ffurl_read_complete(rt->stream, arraydata,
1307  if (inoutsize <= 0)
1308  return AVERROR(EIO);
1309  if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1310  av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1311  " not following standard\n", (int)inoutsize);
1312  return AVERROR(EINVAL);
1313  }
1314 
1315  *first_int = AV_RB32(arraydata);
1316  *second_int = AV_RB32(arraydata + 4);
1317  return 0;
1318 }
1319 
1320 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1321  uint32_t second_int, char *arraydata, int size)
1322 {
1323  int inoutsize;
1324 
1325  AV_WB32(arraydata, first_int);
1326  AV_WB32(arraydata + 4, first_int);
1327  inoutsize = ffurl_write(rt->stream, arraydata,
1329  if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1330  av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1331  return AVERROR(EIO);
1332  }
1333 
1334  return 0;
1335 }
1336 
1337 /**
1338  * rtmp handshake server side
1339  */
1341 {
1343  uint32_t hs_epoch;
1344  uint32_t hs_my_epoch;
1347  uint32_t zeroes;
1348  uint32_t temp = 0;
1349  int randomidx = 0;
1350  int inoutsize = 0;
1351  int ret;
1352 
1353  inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1354  if (inoutsize <= 0) {
1355  av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1356  return AVERROR(EIO);
1357  }
1358  // Check Version
1359  if (buffer[0] != 3) {
1360  av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1361  return AVERROR(EIO);
1362  }
1363  if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1364  av_log(s, AV_LOG_ERROR,
1365  "Unable to write answer - RTMP S0\n");
1366  return AVERROR(EIO);
1367  }
1368  /* Receive C1 */
1369  ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1371  if (ret) {
1372  av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1373  return ret;
1374  }
1375  if (zeroes)
1376  av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1377  /* Send S1 */
1378  /* By now same epoch will be sent */
1379  hs_my_epoch = hs_epoch;
1380  /* Generate random */
1381  for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1382  randomidx += 4)
1383  AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1384 
1385  ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1387  if (ret) {
1388  av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1389  return ret;
1390  }
1391  /* Send S2 */
1392  ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1394  if (ret) {
1395  av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1396  return ret;
1397  }
1398  /* Receive C2 */
1399  ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1401  if (ret) {
1402  av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1403  return ret;
1404  }
1405  if (temp != hs_my_epoch)
1407  "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1408  if (memcmp(buffer + 8, hs_s1 + 8,
1411  "Erroneous C2 Message random does not match up\n");
1412 
1413  return 0;
1414 }
1415 
1417 {
1418  RTMPContext *rt = s->priv_data;
1419  int ret;
1420 
1421  if (pkt->data_size < 4) {
1422  av_log(s, AV_LOG_ERROR,
1423  "Too short chunk size change packet (%d)\n",
1424  pkt->data_size);
1425  return AVERROR_INVALIDDATA;
1426  }
1427 
1428  if (!rt->is_input) {
1429  /* Send the same chunk size change packet back to the server,
1430  * setting the outgoing chunk size to the same as the incoming one. */
1431  if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1432  rt->prev_pkt[1])) < 0)
1433  return ret;
1434  rt->out_chunk_size = AV_RB32(pkt->data);
1435  }
1436 
1437  rt->in_chunk_size = AV_RB32(pkt->data);
1438  if (rt->in_chunk_size <= 0) {
1439  av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1440  rt->in_chunk_size);
1441  return AVERROR_INVALIDDATA;
1442  }
1443  av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1444  rt->in_chunk_size);
1445 
1446  return 0;
1447 }
1448 
1450 {
1451  RTMPContext *rt = s->priv_data;
1452  int t, ret;
1453 
1454  if (pkt->data_size < 2) {
1455  av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1456  pkt->data_size);
1457  return AVERROR_INVALIDDATA;
1458  }
1459 
1460  t = AV_RB16(pkt->data);
1461  if (t == 6) {
1462  if ((ret = gen_pong(s, rt, pkt)) < 0)
1463  return ret;
1464  } else if (t == 26) {
1465  if (rt->swfsize) {
1466  if ((ret = gen_swf_verification(s, rt)) < 0)
1467  return ret;
1468  } else {
1469  av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1470  }
1471  }
1472 
1473  return 0;
1474 }
1475 
1477 {
1478  RTMPContext *rt = s->priv_data;
1479 
1480  if (pkt->data_size < 4) {
1481  av_log(s, AV_LOG_ERROR,
1482  "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1483  pkt->data_size);
1484  return AVERROR_INVALIDDATA;
1485  }
1486 
1487  rt->client_report_size = AV_RB32(pkt->data);
1488  if (rt->client_report_size <= 0) {
1489  av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1490  rt->client_report_size);
1491  return AVERROR_INVALIDDATA;
1492 
1493  }
1494  av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1495  rt->client_report_size >>= 1;
1496 
1497  return 0;
1498 }
1499 
1501 {
1502  RTMPContext *rt = s->priv_data;
1503 
1504  if (pkt->data_size < 4) {
1505  av_log(s, AV_LOG_ERROR,
1506  "Too short server bandwidth report packet (%d)\n",
1507  pkt->data_size);
1508  return AVERROR_INVALIDDATA;
1509  }
1510 
1511  rt->server_bw = AV_RB32(pkt->data);
1512  if (rt->server_bw <= 0) {
1513  av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1514  rt->server_bw);
1515  return AVERROR_INVALIDDATA;
1516  }
1517  av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1518 
1519  return 0;
1520 }
1521 
1522 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1523  const char *opaque, const char *challenge)
1524 {
1525  uint8_t hash[16];
1526  char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1527  struct AVMD5 *md5 = av_md5_alloc();
1528  if (!md5)
1529  return AVERROR(ENOMEM);
1530 
1531  snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1532 
1533  av_md5_init(md5);
1534  av_md5_update(md5, user, strlen(user));
1535  av_md5_update(md5, salt, strlen(salt));
1536  av_md5_update(md5, rt->password, strlen(rt->password));
1537  av_md5_final(md5, hash);
1538  av_base64_encode(hashstr, sizeof(hashstr), hash,
1539  sizeof(hash));
1540  av_md5_init(md5);
1541  av_md5_update(md5, hashstr, strlen(hashstr));
1542  if (opaque)
1543  av_md5_update(md5, opaque, strlen(opaque));
1544  else if (challenge)
1545  av_md5_update(md5, challenge, strlen(challenge));
1546  av_md5_update(md5, challenge2, strlen(challenge2));
1547  av_md5_final(md5, hash);
1548  av_base64_encode(hashstr, sizeof(hashstr), hash,
1549  sizeof(hash));
1550  snprintf(rt->auth_params, sizeof(rt->auth_params),
1551  "?authmod=%s&user=%s&challenge=%s&response=%s",
1552  "adobe", user, challenge2, hashstr);
1553  if (opaque)
1554  av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1555  "&opaque=%s", opaque);
1556 
1557  av_free(md5);
1558  return 0;
1559 }
1560 
1561 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1562 {
1563  uint8_t hash[16];
1564  char hashstr1[33], hashstr2[33];
1565  const char *realm = "live";
1566  const char *method = "publish";
1567  const char *qop = "auth";
1568  const char *nc = "00000001";
1569  char cnonce[10];
1570  struct AVMD5 *md5 = av_md5_alloc();
1571  if (!md5)
1572  return AVERROR(ENOMEM);
1573 
1574  snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1575 
1576  av_md5_init(md5);
1577  av_md5_update(md5, user, strlen(user));
1578  av_md5_update(md5, ":", 1);
1579  av_md5_update(md5, realm, strlen(realm));
1580  av_md5_update(md5, ":", 1);
1581  av_md5_update(md5, rt->password, strlen(rt->password));
1582  av_md5_final(md5, hash);
1583  ff_data_to_hex(hashstr1, hash, 16, 1);
1584  hashstr1[32] = '\0';
1585 
1586  av_md5_init(md5);
1587  av_md5_update(md5, method, strlen(method));
1588  av_md5_update(md5, ":/", 2);
1589  av_md5_update(md5, rt->app, strlen(rt->app));
1590  av_md5_final(md5, hash);
1591  ff_data_to_hex(hashstr2, hash, 16, 1);
1592  hashstr2[32] = '\0';
1593 
1594  av_md5_init(md5);
1595  av_md5_update(md5, hashstr1, strlen(hashstr1));
1596  av_md5_update(md5, ":", 1);
1597  if (nonce)
1598  av_md5_update(md5, nonce, strlen(nonce));
1599  av_md5_update(md5, ":", 1);
1600  av_md5_update(md5, nc, strlen(nc));
1601  av_md5_update(md5, ":", 1);
1602  av_md5_update(md5, cnonce, strlen(cnonce));
1603  av_md5_update(md5, ":", 1);
1604  av_md5_update(md5, qop, strlen(qop));
1605  av_md5_update(md5, ":", 1);
1606  av_md5_update(md5, hashstr2, strlen(hashstr2));
1607  av_md5_final(md5, hash);
1608  ff_data_to_hex(hashstr1, hash, 16, 1);
1609 
1610  snprintf(rt->auth_params, sizeof(rt->auth_params),
1611  "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1612  "llnw", user, nonce, cnonce, nc, hashstr1);
1613 
1614  av_free(md5);
1615  return 0;
1616 }
1617 
1618 static int handle_connect_error(URLContext *s, const char *desc)
1619 {
1620  RTMPContext *rt = s->priv_data;
1621  char buf[300], *ptr, authmod[15];
1622  int i = 0, ret = 0;
1623  const char *user = "", *salt = "", *opaque = NULL,
1624  *challenge = NULL, *cptr = NULL, *nonce = NULL;
1625 
1626  if (!(cptr = strstr(desc, "authmod=adobe")) &&
1627  !(cptr = strstr(desc, "authmod=llnw"))) {
1628  av_log(s, AV_LOG_ERROR,
1629  "Unknown connect error (unsupported authentication method?)\n");
1630  return AVERROR_UNKNOWN;
1631  }
1632  cptr += strlen("authmod=");
1633  while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1634  authmod[i++] = *cptr++;
1635  authmod[i] = '\0';
1636 
1637  if (!rt->username[0] || !rt->password[0]) {
1638  av_log(s, AV_LOG_ERROR, "No credentials set\n");
1639  return AVERROR_UNKNOWN;
1640  }
1641 
1642  if (strstr(desc, "?reason=authfailed")) {
1643  av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1644  return AVERROR_UNKNOWN;
1645  } else if (strstr(desc, "?reason=nosuchuser")) {
1646  av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1647  return AVERROR_UNKNOWN;
1648  }
1649 
1650  if (rt->auth_tried) {
1651  av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1652  return AVERROR_UNKNOWN;
1653  }
1654 
1655  rt->auth_params[0] = '\0';
1656 
1657  if (strstr(desc, "code=403 need auth")) {
1658  snprintf(rt->auth_params, sizeof(rt->auth_params),
1659  "?authmod=%s&user=%s", authmod, rt->username);
1660  return 0;
1661  }
1662 
1663  if (!(cptr = strstr(desc, "?reason=needauth"))) {
1664  av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1665  return AVERROR_UNKNOWN;
1666  }
1667 
1668  av_strlcpy(buf, cptr + 1, sizeof(buf));
1669  ptr = buf;
1670 
1671  while (ptr) {
1672  char *next = strchr(ptr, '&');
1673  char *value = strchr(ptr, '=');
1674  if (next)
1675  *next++ = '\0';
1676  if (value)
1677  *value++ = '\0';
1678  if (!strcmp(ptr, "user")) {
1679  user = value;
1680  } else if (!strcmp(ptr, "salt")) {
1681  salt = value;
1682  } else if (!strcmp(ptr, "opaque")) {
1683  opaque = value;
1684  } else if (!strcmp(ptr, "challenge")) {
1685  challenge = value;
1686  } else if (!strcmp(ptr, "nonce")) {
1687  nonce = value;
1688  }
1689  ptr = next;
1690  }
1691 
1692  if (!strcmp(authmod, "adobe")) {
1693  if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1694  return ret;
1695  } else {
1696  if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1697  return ret;
1698  }
1699 
1700  rt->auth_tried = 1;
1701  return 0;
1702 }
1703 
1705 {
1706  RTMPContext *rt = s->priv_data;
1707  const uint8_t *data_end = pkt->data + pkt->data_size;
1708  char *tracked_method = NULL;
1709  int level = AV_LOG_ERROR;
1710  uint8_t tmpstr[256];
1711  int ret;
1712 
1713  if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1714  return ret;
1715 
1716  if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1717  "description", tmpstr, sizeof(tmpstr))) {
1718  if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1719  !strcmp(tracked_method, "releaseStream") ||
1720  !strcmp(tracked_method, "FCSubscribe") ||
1721  !strcmp(tracked_method, "FCPublish"))) {
1722  /* Gracefully ignore Adobe-specific historical artifact errors. */
1723  level = AV_LOG_WARNING;
1724  ret = 0;
1725  } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1726  ret = handle_connect_error(s, tmpstr);
1727  if (!ret) {
1728  rt->do_reconnect = 1;
1729  level = AV_LOG_VERBOSE;
1730  }
1731  } else
1732  ret = AVERROR_UNKNOWN;
1733  av_log(s, level, "Server error: %s\n", tmpstr);
1734  }
1735 
1736  av_free(tracked_method);
1737  return ret;
1738 }
1739 
1741 {
1742  RTMPContext *rt = s->priv_data;
1743  double seqnum;
1744  char filename[64];
1745  char command[64];
1746  char statusmsg[128];
1747  int stringlen;
1748  char *pchar;
1749  const uint8_t *p = pkt->data;
1750  uint8_t *pp = NULL;
1751  RTMPPacket spkt = { 0 };
1752  GetByteContext gbc;
1753  int ret;
1754 
1755  bytestream2_init(&gbc, p, pkt->data_size);
1756  if (ff_amf_read_string(&gbc, command, sizeof(command),
1757  &stringlen)) {
1758  av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1759  return AVERROR_INVALIDDATA;
1760  }
1761 
1762  ret = ff_amf_read_number(&gbc, &seqnum);
1763  if (ret)
1764  return ret;
1765  ret = ff_amf_read_null(&gbc);
1766  if (ret)
1767  return ret;
1768  if (!strcmp(command, "FCPublish") ||
1769  !strcmp(command, "publish")) {
1770  ret = ff_amf_read_string(&gbc, filename,
1771  sizeof(filename), &stringlen);
1772  // check with url
1773  if (s->filename) {
1774  pchar = strrchr(s->filename, '/');
1775  if (!pchar) {
1777  "Unable to find / in url %s, bad format\n",
1778  s->filename);
1779  pchar = s->filename;
1780  }
1781  pchar++;
1782  if (strcmp(pchar, filename))
1783  av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1784  " %s\n", filename, pchar);
1785  }
1786  rt->state = STATE_RECEIVING;
1787  }
1788 
1789  if (!strcmp(command, "FCPublish")) {
1790  if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1791  RTMP_PT_INVOKE, 0,
1792  RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1793  av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1794  return ret;
1795  }
1796  pp = spkt.data;
1797  ff_amf_write_string(&pp, "onFCPublish");
1798  } else if (!strcmp(command, "publish")) {
1799  PutByteContext pbc;
1800  // Send Stream Begin 1
1801  if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1802  RTMP_PT_PING, 0, 6)) < 0) {
1803  av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1804  return ret;
1805  }
1806  pp = spkt.data;
1807  bytestream2_init_writer(&pbc, pp, spkt.data_size);
1808  bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1809  bytestream2_put_be32(&pbc, rt->nb_streamid);
1810  ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1811  rt->prev_pkt[1]);
1812  ff_rtmp_packet_destroy(&spkt);
1813  if (ret < 0)
1814  return ret;
1815 
1816  // Send onStatus(NetStream.Publish.Start)
1817  if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1818  RTMP_PT_INVOKE, 0,
1819  RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1820  av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1821  return ret;
1822  }
1823  spkt.extra = pkt->extra;
1824  pp = spkt.data;
1825  ff_amf_write_string(&pp, "onStatus");
1826  ff_amf_write_number(&pp, 0);
1827  ff_amf_write_null(&pp);
1828 
1830  ff_amf_write_field_name(&pp, "level");
1831  ff_amf_write_string(&pp, "status");
1832  ff_amf_write_field_name(&pp, "code");
1833  ff_amf_write_string(&pp, "NetStream.Publish.Start");
1834  ff_amf_write_field_name(&pp, "description");
1835  snprintf(statusmsg, sizeof(statusmsg),
1836  "%s is now published", filename);
1837  ff_amf_write_string(&pp, statusmsg);
1838  ff_amf_write_field_name(&pp, "details");
1839  ff_amf_write_string(&pp, filename);
1840  ff_amf_write_field_name(&pp, "clientid");
1841  snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1842  ff_amf_write_string(&pp, statusmsg);
1844 
1845  } else {
1846  if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1847  RTMP_PT_INVOKE, 0,
1848  RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1849  av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1850  return ret;
1851  }
1852  pp = spkt.data;
1853  ff_amf_write_string(&pp, "_result");
1854  ff_amf_write_number(&pp, seqnum);
1855  ff_amf_write_null(&pp);
1856  if (!strcmp(command, "createStream")) {
1857  rt->nb_streamid++;
1858  if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1859  rt->nb_streamid++; /* Values 0 and 2 are reserved */
1860  ff_amf_write_number(&pp, rt->nb_streamid);
1861  /* By now we don't control which streams are removed in
1862  * deleteStream. There is no stream creation control
1863  * if a client creates more than 2^32 - 2 streams. */
1864  }
1865  }
1866  spkt.data_size = pp - spkt.data;
1867  ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1868  rt->prev_pkt[1]);
1869  ff_rtmp_packet_destroy(&spkt);
1870  return ret;
1871 }
1872 
1874 {
1875  RTMPContext *rt = s->priv_data;
1876  char *tracked_method = NULL;
1877  int ret = 0;
1878 
1879  if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1880  return ret;
1881 
1882  if (!tracked_method) {
1883  /* Ignore this reply when the current method is not tracked. */
1884  return ret;
1885  }
1886 
1887  if (!memcmp(tracked_method, "connect", 7)) {
1888  if (!rt->is_input) {
1889  if ((ret = gen_release_stream(s, rt)) < 0)
1890  goto fail;
1891 
1892  if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1893  goto fail;
1894  } else {
1895  if ((ret = gen_server_bw(s, rt)) < 0)
1896  goto fail;
1897  }
1898 
1899  if ((ret = gen_create_stream(s, rt)) < 0)
1900  goto fail;
1901 
1902  if (rt->is_input) {
1903  /* Send the FCSubscribe command when the name of live
1904  * stream is defined by the user or if it's a live stream. */
1905  if (rt->subscribe) {
1906  if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1907  goto fail;
1908  } else if (rt->live == -1) {
1909  if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1910  goto fail;
1911  }
1912  }
1913  } else if (!memcmp(tracked_method, "createStream", 12)) {
1914  //extract a number from the result
1915  if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1916  av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1917  } else {
1918  rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1919  }
1920 
1921  if (!rt->is_input) {
1922  if ((ret = gen_publish(s, rt)) < 0)
1923  goto fail;
1924  } else {
1925  if ((ret = gen_play(s, rt)) < 0)
1926  goto fail;
1927  if ((ret = gen_buffer_time(s, rt)) < 0)
1928  goto fail;
1929  }
1930  }
1931 
1932 fail:
1933  av_free(tracked_method);
1934  return ret;
1935 }
1936 
1938 {
1939  RTMPContext *rt = s->priv_data;
1940  const uint8_t *data_end = pkt->data + pkt->data_size;
1941  const uint8_t *ptr = pkt->data + 11;
1942  uint8_t tmpstr[256];
1943  int i, t;
1944 
1945  for (i = 0; i < 2; i++) {
1946  t = ff_amf_tag_size(ptr, data_end);
1947  if (t < 0)
1948  return 1;
1949  ptr += t;
1950  }
1951 
1952  t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1953  if (!t && !strcmp(tmpstr, "error")) {
1954  if (!ff_amf_get_field_value(ptr, data_end,
1955  "description", tmpstr, sizeof(tmpstr)))
1956  av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1957  return -1;
1958  }
1959 
1960  t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1961  if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1962  if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1963  if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1964  if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1965 
1966  return 0;
1967 }
1968 
1970 {
1971  RTMPContext *rt = s->priv_data;
1972  int ret = 0;
1973 
1974  //TODO: check for the messages sent for wrong state?
1975  if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
1976  if ((ret = handle_invoke_error(s, pkt)) < 0)
1977  return ret;
1978  } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
1979  if ((ret = handle_invoke_result(s, pkt)) < 0)
1980  return ret;
1981  } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
1982  if ((ret = handle_invoke_status(s, pkt)) < 0)
1983  return ret;
1984  } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
1985  if ((ret = gen_check_bw(s, rt)) < 0)
1986  return ret;
1987  } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
1988  !memcmp(pkt->data, "\002\000\011FCPublish", 12) ||
1989  !memcmp(pkt->data, "\002\000\007publish", 10) ||
1990  !memcmp(pkt->data, "\002\000\010_checkbw", 11) ||
1991  !memcmp(pkt->data, "\002\000\014createStream", 15)) {
1992  if ((ret = send_invoke_response(s, pkt)) < 0)
1993  return ret;
1994  }
1995 
1996  return ret;
1997 }
1998 
2000  RTMPContext *rt = s->priv_data;
2001  const uint8_t *p = NULL;
2002  uint8_t *cp = NULL;
2003  uint8_t commandbuffer[64];
2004  char statusmsg[128];
2005  int stringlen;
2006  GetByteContext gbc;
2007  PutByteContext pbc;
2008  uint32_t ts;
2009  int old_flv_size;
2010  const uint8_t *datatowrite;
2011  unsigned datatowritelength;
2012 
2013  p = pkt->data;
2014  bytestream2_init(&gbc, p, pkt->data_size);
2015  if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2016  &stringlen))
2017  return AVERROR_INVALIDDATA;
2018  if (!strcmp(commandbuffer, "@setDataFrame")) {
2019  datatowrite = gbc.buffer;
2020  datatowritelength = bytestream2_get_bytes_left(&gbc);
2021  if (ff_amf_read_string(&gbc, statusmsg,
2022  sizeof(statusmsg), &stringlen))
2023  return AVERROR_INVALIDDATA;
2024  if (strcmp(statusmsg, "onMetaData")) {
2025  av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
2026  statusmsg);
2027  return 0;
2028  }
2029 
2030  /* Provide ECMAArray to flv */
2031  ts = pkt->timestamp;
2032 
2033  // generate packet header and put data into buffer for FLV demuxer
2034  if (rt->flv_off < rt->flv_size) {
2035  old_flv_size = rt->flv_size;
2036  rt->flv_size += datatowritelength + 15;
2037  } else {
2038  old_flv_size = 0;
2039  rt->flv_size = datatowritelength + 15;
2040  rt->flv_off = 0;
2041  }
2042 
2043  cp = av_realloc(rt->flv_data, rt->flv_size);
2044  if (!cp)
2045  return AVERROR(ENOMEM);
2046  rt->flv_data = cp;
2047  bytestream2_init_writer(&pbc, cp, rt->flv_size);
2048  bytestream2_skip_p(&pbc, old_flv_size);
2049  bytestream2_put_byte(&pbc, pkt->type);
2050  bytestream2_put_be24(&pbc, datatowritelength);
2051  bytestream2_put_be24(&pbc, ts);
2052  bytestream2_put_byte(&pbc, ts >> 24);
2053  bytestream2_put_be24(&pbc, 0);
2054  bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2055  bytestream2_put_be32(&pbc, 0);
2056  }
2057  return 0;
2058 }
2059 
2060 /**
2061  * Parse received packet and possibly perform some action depending on
2062  * the packet contents.
2063  * @return 0 for no errors, negative values for serious errors which prevent
2064  * further communications, positive values for uncritical errors
2065  */
2067 {
2068  int ret;
2069 
2070 #ifdef DEBUG
2071  ff_rtmp_packet_dump(s, pkt);
2072 #endif
2073 
2074  switch (pkt->type) {
2075  case RTMP_PT_BYTES_READ:
2076  av_dlog(s, "received bytes read report\n");
2077  break;
2078  case RTMP_PT_CHUNK_SIZE:
2079  if ((ret = handle_chunk_size(s, pkt)) < 0)
2080  return ret;
2081  break;
2082  case RTMP_PT_PING:
2083  if ((ret = handle_ping(s, pkt)) < 0)
2084  return ret;
2085  break;
2086  case RTMP_PT_CLIENT_BW:
2087  if ((ret = handle_client_bw(s, pkt)) < 0)
2088  return ret;
2089  break;
2090  case RTMP_PT_SERVER_BW:
2091  if ((ret = handle_server_bw(s, pkt)) < 0)
2092  return ret;
2093  break;
2094  case RTMP_PT_INVOKE:
2095  if ((ret = handle_invoke(s, pkt)) < 0)
2096  return ret;
2097  break;
2098  case RTMP_PT_VIDEO:
2099  case RTMP_PT_AUDIO:
2100  case RTMP_PT_METADATA:
2101  case RTMP_PT_NOTIFY:
2102  /* Audio, Video and Metadata packets are parsed in get_packet() */
2103  break;
2104  default:
2105  av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2106  break;
2107  }
2108  return 0;
2109 }
2110 
2111 /**
2112  * Interact with the server by receiving and sending RTMP packets until
2113  * there is some significant data (media data or expected status notification).
2114  *
2115  * @param s reading context
2116  * @param for_header non-zero value tells function to work until it
2117  * gets notification from the server that playing has been started,
2118  * otherwise function will work until some media data is received (or
2119  * an error happens)
2120  * @return 0 for successful operation, negative value in case of error
2121  */
2122 static int get_packet(URLContext *s, int for_header)
2123 {
2124  RTMPContext *rt = s->priv_data;
2125  int ret;
2126  uint8_t *p;
2127  const uint8_t *next;
2128  uint32_t data_size;
2129  uint32_t ts, cts, pts=0;
2130 
2131  if (rt->state == STATE_STOPPED)
2132  return AVERROR_EOF;
2133 
2134  for (;;) {
2135  RTMPPacket rpkt = { 0 };
2136  if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2137  rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2138  if (ret == 0) {
2139  return AVERROR(EAGAIN);
2140  } else {
2141  return AVERROR(EIO);
2142  }
2143  }
2144  rt->bytes_read += ret;
2145  if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2146  av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2147  if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2148  return ret;
2149  rt->last_bytes_read = rt->bytes_read;
2150  }
2151 
2152  ret = rtmp_parse_result(s, rt, &rpkt);
2153  if (ret < 0) {//serious error in current packet
2154  ff_rtmp_packet_destroy(&rpkt);
2155  return ret;
2156  }
2157  if (rt->do_reconnect && for_header) {
2158  ff_rtmp_packet_destroy(&rpkt);
2159  return 0;
2160  }
2161  if (rt->state == STATE_STOPPED) {
2162  ff_rtmp_packet_destroy(&rpkt);
2163  return AVERROR_EOF;
2164  }
2165  if (for_header && (rt->state == STATE_PLAYING ||
2166  rt->state == STATE_PUBLISHING ||
2167  rt->state == STATE_RECEIVING)) {
2168  ff_rtmp_packet_destroy(&rpkt);
2169  return 0;
2170  }
2171  if (!rpkt.data_size || !rt->is_input) {
2172  ff_rtmp_packet_destroy(&rpkt);
2173  continue;
2174  }
2175  if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2176  (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
2177  ts = rpkt.timestamp;
2178 
2179  // generate packet header and put data into buffer for FLV demuxer
2180  rt->flv_off = 0;
2181  rt->flv_size = rpkt.data_size + 15;
2182  rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2183  bytestream_put_byte(&p, rpkt.type);
2184  bytestream_put_be24(&p, rpkt.data_size);
2185  bytestream_put_be24(&p, ts);
2186  bytestream_put_byte(&p, ts >> 24);
2187  bytestream_put_be24(&p, 0);
2188  bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
2189  bytestream_put_be32(&p, 0);
2190  ff_rtmp_packet_destroy(&rpkt);
2191  return 0;
2192  } else if (rpkt.type == RTMP_PT_NOTIFY) {
2193  ret = handle_notify(s, &rpkt);
2194  ff_rtmp_packet_destroy(&rpkt);
2195  if (ret) {
2196  av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2197  return ret;
2198  }
2199  return 0;
2200  } else if (rpkt.type == RTMP_PT_METADATA) {
2201  // we got raw FLV data, make it available for FLV demuxer
2202  rt->flv_off = 0;
2203  rt->flv_size = rpkt.data_size;
2204  rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2205  /* rewrite timestamps */
2206  next = rpkt.data;
2207  ts = rpkt.timestamp;
2208  while (next - rpkt.data < rpkt.data_size - 11) {
2209  next++;
2210  data_size = bytestream_get_be24(&next);
2211  p=next;
2212  cts = bytestream_get_be24(&next);
2213  cts |= bytestream_get_byte(&next) << 24;
2214  if (pts==0)
2215  pts=cts;
2216  ts += cts - pts;
2217  pts = cts;
2218  bytestream_put_be24(&p, ts);
2219  bytestream_put_byte(&p, ts >> 24);
2220  next += data_size + 3 + 4;
2221  }
2222  memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
2223  ff_rtmp_packet_destroy(&rpkt);
2224  return 0;
2225  }
2226  ff_rtmp_packet_destroy(&rpkt);
2227  }
2228 }
2229 
2230 static int rtmp_close(URLContext *h)
2231 {
2232  RTMPContext *rt = h->priv_data;
2233  int ret = 0;
2234 
2235  if (!rt->is_input) {
2236  rt->flv_data = NULL;
2237  if (rt->out_pkt.data_size)
2239  if (rt->state > STATE_FCPUBLISH)
2240  ret = gen_fcunpublish_stream(h, rt);
2241  }
2242  if (rt->state > STATE_HANDSHAKED)
2243  ret = gen_delete_stream(h, rt);
2244 
2246  av_freep(&rt->flv_data);
2247  ffurl_close(rt->stream);
2248  return ret;
2249 }
2250 
2251 /**
2252  * Open RTMP connection and verify that the stream can be played.
2253  *
2254  * URL syntax: rtmp://server[:port][/app][/playpath]
2255  * where 'app' is first one or two directories in the path
2256  * (e.g. /ondemand/, /flash/live/, etc.)
2257  * and 'playpath' is a file name (the rest of the path,
2258  * may be prefixed with "mp4:")
2259  */
2260 static int rtmp_open(URLContext *s, const char *uri, int flags)
2261 {
2262  RTMPContext *rt = s->priv_data;
2263  char proto[8], hostname[256], path[1024], auth[100], *fname;
2264  char *old_app;
2265  uint8_t buf[2048];
2266  int port;
2267  AVDictionary *opts = NULL;
2268  int ret;
2269 
2270  if (rt->listen_timeout > 0)
2271  rt->listen = 1;
2272 
2273  rt->is_input = !(flags & AVIO_FLAG_WRITE);
2274 
2275  av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2276  hostname, sizeof(hostname), &port,
2277  path, sizeof(path), s->filename);
2278 
2279  if (auth[0]) {
2280  char *ptr = strchr(auth, ':');
2281  if (ptr) {
2282  *ptr = '\0';
2283  av_strlcpy(rt->username, auth, sizeof(rt->username));
2284  av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2285  }
2286  }
2287 
2288  if (rt->listen && strcmp(proto, "rtmp")) {
2289  av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2290  proto);
2291  return AVERROR(EINVAL);
2292  }
2293  if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2294  if (!strcmp(proto, "rtmpts"))
2295  av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2296 
2297  /* open the http tunneling connection */
2298  ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2299  } else if (!strcmp(proto, "rtmps")) {
2300  /* open the tls connection */
2301  if (port < 0)
2302  port = RTMPS_DEFAULT_PORT;
2303  ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2304  } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2305  if (!strcmp(proto, "rtmpte"))
2306  av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2307 
2308  /* open the encrypted connection */
2309  ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2310  rt->encrypted = 1;
2311  } else {
2312  /* open the tcp connection */
2313  if (port < 0)
2314  port = RTMP_DEFAULT_PORT;
2315  if (rt->listen)
2316  ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2317  "?listen&listen_timeout=%d",
2318  rt->listen_timeout * 1000);
2319  else
2320  ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2321  }
2322 
2323 reconnect:
2324  if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2325  &s->interrupt_callback, &opts)) < 0) {
2326  av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2327  goto fail;
2328  }
2329 
2330  if (rt->swfverify) {
2331  if ((ret = rtmp_calc_swfhash(s)) < 0)
2332  goto fail;
2333  }
2334 
2335  rt->state = STATE_START;
2336  if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2337  goto fail;
2338  if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2339  goto fail;
2340 
2341  rt->out_chunk_size = 128;
2342  rt->in_chunk_size = 128; // Probably overwritten later
2343  rt->state = STATE_HANDSHAKED;
2344 
2345  // Keep the application name when it has been defined by the user.
2346  old_app = rt->app;
2347 
2348  rt->app = av_malloc(APP_MAX_LENGTH);
2349  if (!rt->app) {
2350  ret = AVERROR(ENOMEM);
2351  goto fail;
2352  }
2353 
2354  //extract "app" part from path
2355  if (!strncmp(path, "/ondemand/", 10)) {
2356  fname = path + 10;
2357  memcpy(rt->app, "ondemand", 9);
2358  } else {
2359  char *next = *path ? path + 1 : path;
2360  char *p = strchr(next, '/');
2361  if (!p) {
2362  fname = next;
2363  rt->app[0] = '\0';
2364  } else {
2365  // make sure we do not mismatch a playpath for an application instance
2366  char *c = strchr(p + 1, ':');
2367  fname = strchr(p + 1, '/');
2368  if (!fname || (c && c < fname)) {
2369  fname = p + 1;
2370  av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2371  } else {
2372  fname++;
2373  av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2374  }
2375  }
2376  }
2377 
2378  if (old_app) {
2379  // The name of application has been defined by the user, override it.
2380  if (strlen(old_app) >= APP_MAX_LENGTH) {
2381  ret = AVERROR(EINVAL);
2382  goto fail;
2383  }
2384  av_free(rt->app);
2385  rt->app = old_app;
2386  }
2387 
2388  if (!rt->playpath) {
2389  int len = strlen(fname);
2390 
2392  if (!rt->playpath) {
2393  ret = AVERROR(ENOMEM);
2394  goto fail;
2395  }
2396 
2397  if (!strchr(fname, ':') && len >= 4 &&
2398  (!strcmp(fname + len - 4, ".f4v") ||
2399  !strcmp(fname + len - 4, ".mp4"))) {
2400  memcpy(rt->playpath, "mp4:", 5);
2401  } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2402  fname[len - 4] = '\0';
2403  } else {
2404  rt->playpath[0] = 0;
2405  }
2407  }
2408 
2409  if (!rt->tcurl) {
2411  if (!rt->tcurl) {
2412  ret = AVERROR(ENOMEM);
2413  goto fail;
2414  }
2415  ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2416  port, "/%s", rt->app);
2417  }
2418 
2419  if (!rt->flashver) {
2421  if (!rt->flashver) {
2422  ret = AVERROR(ENOMEM);
2423  goto fail;
2424  }
2425  if (rt->is_input) {
2426  snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2429  } else {
2431  "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2432  }
2433  }
2434 
2435  rt->client_report_size = 1048576;
2436  rt->bytes_read = 0;
2437  rt->last_bytes_read = 0;
2438  rt->server_bw = 2500000;
2439 
2440  av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2441  proto, path, rt->app, rt->playpath);
2442  if (!rt->listen) {
2443  if ((ret = gen_connect(s, rt)) < 0)
2444  goto fail;
2445  } else {
2446  if (read_connect(s, s->priv_data) < 0)
2447  goto fail;
2448  rt->is_input = 1;
2449  }
2450 
2451  do {
2452  ret = get_packet(s, 1);
2453  } while (ret == EAGAIN);
2454  if (ret < 0)
2455  goto fail;
2456 
2457  if (rt->do_reconnect) {
2458  ffurl_close(rt->stream);
2459  rt->stream = NULL;
2460  rt->do_reconnect = 0;
2461  rt->nb_invokes = 0;
2462  memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2464  goto reconnect;
2465  }
2466 
2467  if (rt->is_input) {
2468  // generate FLV header for demuxer
2469  rt->flv_size = 13;
2470  rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2471  rt->flv_off = 0;
2472  memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2473  } else {
2474  rt->flv_size = 0;
2475  rt->flv_data = NULL;
2476  rt->flv_off = 0;
2477  rt->skip_bytes = 13;
2478  }
2479 
2481  s->is_streamed = 1;
2482  return 0;
2483 
2484 fail:
2485  av_dict_free(&opts);
2486  rtmp_close(s);
2487  return ret;
2488 }
2489 
2490 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2491 {
2492  RTMPContext *rt = s->priv_data;
2493  int orig_size = size;
2494  int ret;
2495 
2496  while (size > 0) {
2497  int data_left = rt->flv_size - rt->flv_off;
2498 
2499  if (data_left >= size) {
2500  memcpy(buf, rt->flv_data + rt->flv_off, size);
2501  rt->flv_off += size;
2502  return orig_size;
2503  }
2504  if (data_left > 0) {
2505  memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2506  buf += data_left;
2507  size -= data_left;
2508  rt->flv_off = rt->flv_size;
2509  return data_left;
2510  }
2511  if ((ret = get_packet(s, 0)) < 0)
2512  return ret;
2513  }
2514  return orig_size;
2515 }
2516 
2517 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2518 {
2519  RTMPContext *rt = s->priv_data;
2520  int size_temp = size;
2521  int pktsize, pkttype;
2522  uint32_t ts;
2523  const uint8_t *buf_temp = buf;
2524  uint8_t c;
2525  int ret;
2526 
2527  do {
2528  if (rt->skip_bytes) {
2529  int skip = FFMIN(rt->skip_bytes, size_temp);
2530  buf_temp += skip;
2531  size_temp -= skip;
2532  rt->skip_bytes -= skip;
2533  continue;
2534  }
2535 
2536  if (rt->flv_header_bytes < 11) {
2537  const uint8_t *header = rt->flv_header;
2538  int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2539  bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2540  rt->flv_header_bytes += copy;
2541  size_temp -= copy;
2542  if (rt->flv_header_bytes < 11)
2543  break;
2544 
2545  pkttype = bytestream_get_byte(&header);
2546  pktsize = bytestream_get_be24(&header);
2547  ts = bytestream_get_be24(&header);
2548  ts |= bytestream_get_byte(&header) << 24;
2549  bytestream_get_be24(&header);
2550  rt->flv_size = pktsize;
2551 
2552  //force 12bytes header
2553  if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2554  pkttype == RTMP_PT_NOTIFY) {
2555  if (pkttype == RTMP_PT_NOTIFY)
2556  pktsize += 16;
2558  }
2559 
2560  //this can be a big packet, it's better to send it right here
2562  pkttype, ts, pktsize)) < 0)
2563  return ret;
2564 
2565  rt->out_pkt.extra = rt->main_channel_id;
2566  rt->flv_data = rt->out_pkt.data;
2567 
2568  if (pkttype == RTMP_PT_NOTIFY)
2569  ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2570  }
2571 
2572  if (rt->flv_size - rt->flv_off > size_temp) {
2573  bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2574  rt->flv_off += size_temp;
2575  size_temp = 0;
2576  } else {
2577  bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2578  size_temp -= rt->flv_size - rt->flv_off;
2579  rt->flv_off += rt->flv_size - rt->flv_off;
2580  }
2581 
2582  if (rt->flv_off == rt->flv_size) {
2583  rt->skip_bytes = 4;
2584 
2585  if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2586  return ret;
2587  rt->flv_size = 0;
2588  rt->flv_off = 0;
2589  rt->flv_header_bytes = 0;
2590  rt->flv_nb_packets++;
2591  }
2592  } while (buf_temp - buf < size);
2593 
2594  if (rt->flv_nb_packets < rt->flush_interval)
2595  return size;
2596  rt->flv_nb_packets = 0;
2597 
2598  /* set stream into nonblocking mode */
2600 
2601  /* try to read one byte from the stream */
2602  ret = ffurl_read(rt->stream, &c, 1);
2603 
2604  /* switch the stream back into blocking mode */
2605  rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2606 
2607  if (ret == AVERROR(EAGAIN)) {
2608  /* no incoming data to handle */
2609  return size;
2610  } else if (ret < 0) {
2611  return ret;
2612  } else if (ret == 1) {
2613  RTMPPacket rpkt = { 0 };
2614 
2615  if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2616  rt->in_chunk_size,
2617  rt->prev_pkt[0], c)) <= 0)
2618  return ret;
2619 
2620  if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2621  return ret;
2622 
2623  ff_rtmp_packet_destroy(&rpkt);
2624  }
2625 
2626  return size;
2627 }
2628 
2629 #define OFFSET(x) offsetof(RTMPContext, x)
2630 #define DEC AV_OPT_FLAG_DECODING_PARAM
2631 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2632 
2633 static const AVOption rtmp_options[] = {
2634  {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2635  {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {.i64 = 3000}, 0, INT_MAX, DEC|ENC},
2636  {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2637  {"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},
2638  {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {.i64 = 10}, 0, INT_MAX, ENC},
2639  {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {.i64 = -2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
2640  {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2641  {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2642  {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2643  {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2644  {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2645  {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2646  {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2647  {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2648  {"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},
2649  {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2650  {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2651  {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2652  {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1", OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2653  { NULL },
2654 };
2655 
2656 #define RTMP_PROTOCOL(flavor) \
2657 static const AVClass flavor##_class = { \
2658  .class_name = #flavor, \
2659  .item_name = av_default_item_name, \
2660  .option = rtmp_options, \
2661  .version = LIBAVUTIL_VERSION_INT, \
2662 }; \
2663  \
2664 URLProtocol ff_##flavor##_protocol = { \
2665  .name = #flavor, \
2666  .url_open = rtmp_open, \
2667  .url_read = rtmp_read, \
2668  .url_write = rtmp_write, \
2669  .url_close = rtmp_close, \
2670  .priv_data_size = sizeof(RTMPContext), \
2671  .flags = URL_PROTOCOL_FLAG_NETWORK, \
2672  .priv_data_class= &flavor##_class, \
2673 };
2674 
2675 
2676 RTMP_PROTOCOL(rtmp)
2677 RTMP_PROTOCOL(rtmpe)
2678 RTMP_PROTOCOL(rtmps)
2679 RTMP_PROTOCOL(rtmpt)
2680 RTMP_PROTOCOL(rtmpte)
2681 RTMP_PROTOCOL(rtmpts)
static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
Generate report on bytes read so far and send it to the server.
Definition: rtmpproto.c:826
Definition: lfg.h:25
void av_sha_final(AVSHA *ctx, uint8_t *digest)
Finish hashing and output digest value.
Definition: sha.c:320
#define RTMP_CLIENT_VER4
Definition: rtmp.h:43
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
static int gen_swf_verification(URLContext *s, RTMPContext *rt)
Generate SWF verification message and send it to the server.
Definition: rtmpproto.c:765
static int rtmp_read(URLContext *s, uint8_t *buf, int size)
Definition: rtmpproto.c:2490
video packet
Definition: rtmppkt.h:54
const char * s
Definition: avisynth_c.h:668
int live
0: recorded, -1: live, -2: both
Definition: rtmpproto.c:84
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int ff_amf_read_null(GetByteContext *bc)
Read AMF NULL value.
Definition: rtmppkt.c:125
void av_sha_update(AVSHA *ctx, const uint8_t *data, unsigned int len)
Update hash value.
Definition: sha.c:293
AVOption.
Definition: opt.h:251
hash context
Definition: sha.c:32
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
Definition: rtmpproto.c:2517
static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1704
client bandwidth
Definition: rtmppkt.h:52
static int handle_invoke(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1969
#define RTMP_CLIENT_VER2
Definition: rtmp.h:41
int av_sha_init(AVSHA *ctx, int bits)
Initialize SHA-1 or SHA-2 hashing.
Definition: sha.c:252
static int gen_check_bw(URLContext *s, RTMPContext *rt)
Generate check bandwidth message and send it to the server.
Definition: rtmpproto.c:805
static const uint8_t rtmp_server_key[]
Key used for RTMP server digest signing.
Definition: rtmpproto.c:141
#define AV_RB64
else temp
Definition: vf_mcdeint.c:148
int data_size
packet payload size
Definition: rtmppkt.h:84
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: avio.c:317
#define RTMPS_DEFAULT_PORT
Definition: rtmp.h:28
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:48
static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt, const char *subscribe)
Definition: rtmpproto.c:842
void ff_amf_write_field_name(uint8_t **dst, const char *str)
Write string used as field name in AMF object to buffer.
Definition: rtmppkt.c:73
int flv_header_bytes
number of initialized bytes in flv_header
Definition: rtmpproto.c:99
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
static int hash(int head, const int add)
Hash function adding character.
Definition: lzwenc.c:74
AVIOInterruptCB interrupt_callback
Definition: url.h:50
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
Definition: bytestream.h:139
#define AVIO_FLAG_READ
read-only
Definition: avio.h:332
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:333
int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
Calculate number of bytes taken by first AMF entry in data.
Definition: rtmppkt.c:337
static int gen_create_stream(URLContext *s, RTMPContext *rt)
Generate &#39;createStream&#39; call and send it to the server.
Definition: rtmpproto.c:614
#define TCURL_MAX_LENGTH
Definition: rtmpproto.c:55
struct RTMPContext RTMPContext
protocol handler context
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:130
int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket *prev_pkt)
Read RTMP packet sent by the server.
Definition: rtmppkt.c:132
int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags)
Definition: opt.c:409
int flags
Definition: url.h:46
URLContext * stream
TCP stream used in interactions with RTMP server.
Definition: rtmpproto.c:78
void * av_realloc(void *ptr, size_t size)
Allocate or reallocate a block of memory.
Definition: mem.c:141
av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (%s)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic?ac->func_descr_generic:ac->func_descr)
int in_chunk_size
size of the chunks incoming RTMP packets are divided into
Definition: rtmpproto.c:80
#define RTMP_CHANNELS
maximum possible number of different RTMP channels
Definition: rtmppkt.h:30
int skip_bytes
number of bytes to skip from the input FLV stream in the next write call
Definition: rtmpproto.c:97
#define DEC
Definition: rtmpproto.c:2630
uint32_t last_bytes_read
number of bytes read last reported to server
Definition: rtmpproto.c:96
static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
rtmp handshake server side
Definition: rtmpproto.c:1340
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...) av_printf_format(7
Assemble a URL string from components.
RTMPPacketType type
packet payload type
Definition: rtmppkt.h:79
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
channel for sending a/v to server
Definition: rtmppkt.h:39
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
ping
Definition: rtmppkt.h:50
#define AV_WB32(p, darg)
Definition: intreadwrite.h:265
int flv_nb_packets
number of flv packets published
Definition: rtmpproto.c:92
char password[50]
Definition: rtmpproto.c:122
static const char signature[]
Definition: ipmovie.c:526
struct AVMD5 * av_md5_alloc(void)
Definition: md5.c:47
int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap, const uint8_t *key, int keylen, uint8_t *dst)
Calculate HMAC-SHA2 digest for RTMP handshake packets.
Definition: rtmpproto.c:862
static av_always_inline double av_int2double(uint64_t i)
Reinterpret a 64-bit integer as a double.
Definition: intfloat.h:60
uint8_t
AVOptions.
#define RTMP_DEFAULT_PORT
Definition: rtmp.h:27
uint32_t extra
probably an additional channel ID used during streaming data
Definition: rtmppkt.h:82
ClientState state
current state
Definition: rtmpproto.c:87
#define AV_RB32
static AVPacket pkt
Definition: demuxing.c:56
static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
Generate &#39;FCUnpublish&#39; call and send it to the server.
Definition: rtmpproto.c:590
#define RTMP_PKTDATA_DEFAULT_SIZE
Definition: rtmpproto.c:57
TrackedMethod * tracked_methods
tracked methods buffer
Definition: rtmpproto.c:115
double strtod(const char *, char **)
void ff_amf_write_string(uint8_t **dst, const char *str)
Write string in AMF format to buffer.
Definition: rtmppkt.c:43
static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
Definition: rtmpproto.c:245
const uint8_t * buffer
Definition: bytestream.h:33
int ff_rtmpe_compute_secret_key(URLContext *h, const uint8_t *serverdata, const uint8_t *clientdata, int type)
Compute the shared secret key and initialize the RC4 encryption.
Definition: rtmpcrypt.c:145
void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
Print information and contents of RTMP packet.
Definition: rtmppkt.c:502
int nb_invokes
keeps track of invoke messages
Definition: rtmpproto.c:100
int out_chunk_size
size of the chunks outgoing RTMP packets are divided into
Definition: rtmpproto.c:81
#define AVERROR_EOF
End of file.
Definition: error.h:55
int flv_size
current buffer size
Definition: rtmpproto.c:90
int listen_timeout
listen timeout to wait for new connections
Definition: rtmpproto.c:119
int flush_interval
number of packets flushed in the same request (RTMPT only)
Definition: rtmpproto.c:113
#define APP_MAX_LENGTH
Definition: rtmpproto.c:53
static void copy(LZOContext *c, int cnt)
Copies bytes from input to output buffer with checking.
Definition: lzo.c:79
char * swfverify
URL to player swf file, compute hash/size automatically.
Definition: rtmpproto.c:107
static int rtmp_handshake(URLContext *s, RTMPContext *rt)
Perform handshake with the server by means of exchanging pseudorandom data signed with HMAC-SHA2 dige...
Definition: rtmpproto.c:1120
int encrypted
use an encrypted connection (RTMPE only)
Definition: rtmpproto.c:114
int ff_rtmpe_gen_pub_key(URLContext *h, uint8_t *buf)
Initialize the Diffie-Hellmann context and generate the public key.
Definition: rtmpcrypt.c:122
Definition: md5.c:39
int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val, int add_val)
Calculate digest position for RTMP handshake packets.
Definition: rtmpproto.c:904
void ff_amf_write_object_end(uint8_t **dst)
Write marker for end of AMF object to buffer.
Definition: rtmppkt.c:79
char * conn
append arbitrary AMF data to the Connect message
Definition: rtmpproto.c:86
static void del_tracked_method(RTMPContext *rt, int index)
Definition: rtmpproto.c:173
static int rtmp_validate_digest(uint8_t *buf, int off)
Verify that the received server response has the expected digest value.
Definition: rtmpproto.c:949
void ff_amf_write_bool(uint8_t **dst, int val)
Write boolean value in AMF format to buffer.
Definition: rtmppkt.c:31
static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt, const char *opaque, const char *challenge)
Definition: rtmpproto.c:1522
static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
Put HMAC-SHA2 digest of packet data (except for the bytes where this digest will be stored) into that...
Definition: rtmpproto.c:924
number of bytes read
Definition: rtmppkt.h:49
char * name
Definition: rtmpproto.c:71
static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1476
void av_md5_update(AVMD5 *ctx, const uint8_t *src, const int len)
Definition: md5.c:142
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
char * pageurl
url of the web page
Definition: rtmpproto.c:109
char auth_params[500]
Definition: rtmpproto.c:123
string username
Definition: lastfm_tags.py:48
static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
Definition: rtmpproto.c:217
#define AV_RB16
char * flashver
version of the flash plugin
Definition: rtmpproto.c:102
static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1937
ClientState
RTMP protocol handler state.
Definition: rtmpproto.c:60
char * swfurl
url of the swf player
Definition: rtmpproto.c:106
int main_channel_id
an additional channel ID which is used for some invocations
Definition: rtmpproto.c:88
#define PLAYER_KEY_OPEN_PART_LEN
length of partial key used for first client digest signing
Definition: rtmpproto.c:128
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:162
audio packet
Definition: rtmppkt.h:53
static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
Generate &#39;FCPublish&#39; call and send it to the server.
Definition: rtmpproto.c:566
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:149
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
static int gen_delete_stream(URLContext *s, RTMPContext *rt)
Generate &#39;deleteStream&#39; call and send it to the server.
Definition: rtmpproto.c:639
char * playpath
stream identifier to play (with possible "mp4:" prefix)
Definition: rtmpproto.c:83
client has not done anything yet
Definition: rtmpproto.c:61
static const uint8_t offset[127][2]
Definition: vf_spp.c:70
char * av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
Encode data to base64 and null-terminate.
static void free_tracked_methods(RTMPContext *rt)
Definition: rtmpproto.c:205
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:82
int size
int tracked_methods_size
size of the tracked methods buffer
Definition: rtmpproto.c:117
#define RTMP_PROTOCOL(flavor)
Definition: rtmpproto.c:2656
#define OFFSET(x)
Definition: rtmpproto.c:2629
client has performed handshake
Definition: rtmpproto.c:62
static int gen_play(URLContext *s, RTMPContext *rt)
Generate &#39;play&#39; call and send it to the server, then ping the server to start actual playing...
Definition: rtmpproto.c:685
#define AV_LOG_VERBOSE
Definition: log.h:157
static av_always_inline void bytestream2_skip_p(PutByteContext *p, unsigned int size)
Definition: bytestream.h:171
#define PLAYPATH_MAX_LENGTH
Definition: rtmpproto.c:54
int swfhash_len
length of the SHA256 hash
Definition: rtmpproto.c:104
#define LIBAVFORMAT_IDENT
#define CONFIG_FFRTMPCRYPT_PROTOCOL
Definition: config.h:1519
server bandwidth
Definition: rtmppkt.h:51
RTMPPacket prev_pkt[2][RTMP_CHANNELS]
packet history used when reading and sending packets
Definition: rtmpproto.c:79
static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
Parse received packet and possibly perform some action depending on the packet contents.
Definition: rtmpproto.c:2066
#define AV_BASE64_SIZE(x)
Calculate the output size needed to base64-encode x bytes to a null-terminated string.
Definition: base64.h:61
#define FFMIN(a, b)
Definition: common.h:58
client has started sending multimedia data to server (for output)
Definition: rtmpproto.c:65
void ff_rtmp_packet_destroy(RTMPPacket *pkt)
Free RTMP packet.
Definition: rtmppkt.c:329
int auth_tried
Definition: rtmpproto.c:125
ret
Definition: avfilter.c:821
static int gen_publish(URLContext *s, RTMPContext *rt)
Generate &#39;publish&#39; call and send it to the server.
Definition: rtmpproto.c:712
client has started receiving multimedia data from server
Definition: rtmpproto.c:64
int client_buffer_time
client buffer time in ms
Definition: rtmpproto.c:112
client FCPublishing stream (for output)
Definition: rtmpproto.c:63
t
Definition: genspecsines3.m:6
int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end, const uint8_t *name, uint8_t *dst, int dst_size)
Retrieve value of given AMF object field in string form.
Definition: rtmppkt.c:373
static int rtmp_close(URLContext *h)
Definition: rtmpproto.c:2230
int nb_streamid
The next stream id to return on createStream calls.
Definition: rtmpproto.c:120
#define ENC
Definition: rtmpproto.c:2631
#define RTMP_CLIENT_PLATFORM
emulated Flash client version - 9.0.124.2 on Linux
Definition: rtmp.h:39
static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
Generate ping reply and send it to the server.
Definition: rtmpproto.c:739
static int add_tracked_method(RTMPContext *rt, const char *name, int id)
Definition: rtmpproto.c:151
int is_input
input/output flag
Definition: rtmpproto.c:82
static const uint8_t rtmp_player_key[]
Client key used for digest signing.
Definition: rtmpproto.c:130
received a publish command (for input)
Definition: rtmpproto.c:66
static int rtmp_send_hs_packet(RTMPContext *rt, uint32_t first_int, uint32_t second_int, char *arraydata, int size)
Definition: rtmpproto.c:1320
static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, uint8_t *dst, unsigned int size)
Definition: bytestream.h:328
static int gen_buffer_time(URLContext *s, RTMPContext *rt)
Generate client buffer time and send it to the server.
Definition: rtmpproto.c:663
FIXME Range Coding of cr are level
Definition: snow.txt:367
static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, const uint8_t *src, unsigned int size)
Definition: bytestream.h:277
the broadcast has been stopped
Definition: rtmpproto.c:67
char * swfhash
SHA256 hash of the decompressed SWF file (32 bytes)
Definition: rtmpproto.c:103
char swfverification[42]
hash of the SWF verification
Definition: rtmpproto.c:108
int nb_tracked_methods
number of tracked methods
Definition: rtmpproto.c:116
offset must point to a pointer immediately followed by an int for the length
Definition: opt.h:228
NULL
Definition: eval.c:55
static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
Definition: rtmpproto.c:1561
chunk size change
Definition: rtmppkt.h:48
char username[50]
Definition: rtmpproto.c:121
FLV common header.
int flv_off
number of bytes read from current buffer
Definition: rtmpproto.c:91
int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, int chunk_size, RTMPPacket *prev_pkt)
Send RTMP packet to the server.
Definition: rtmppkt.c:234
AVS_Value src
Definition: avisynth_c.h:523
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:220
static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1416
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:351
uint32_t bytes_read
number of bytes read from server
Definition: rtmpproto.c:95
static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Definition: vf_drawtext.c:596
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
struct AVSHA * av_sha_alloc(void)
Allocate an AVSHA context.
Definition: sha.c:43
void av_md5_init(AVMD5 *ctx)
Definition: md5.c:132
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:38
void * buf
Definition: avisynth_c.h:594
Definition: url.h:41
char * subscribe
name of live stream to subscribe
Definition: rtmpproto.c:110
void ff_rtmpe_encrypt_sig(URLContext *h, uint8_t *sig, const uint8_t *digest, int type)
Encrypt the signature.
Definition: rtmpcrypt.c:207
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition: avio.h:334
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:62
channel for sending server control messages
Definition: rtmppkt.h:38
static int gen_connect(URLContext *s, RTMPContext *rt)
Generate &#39;connect&#39; call and send it to the server.
Definition: rtmpproto.c:308
static int gen_release_stream(URLContext *s, RTMPContext *rt)
Generate &#39;releaseStream&#39; call and send it to the server.
Definition: rtmpproto.c:542
#define HMAC_OPAD_VAL
Definition: rtmp.h:33
double value
Definition: eval.c:82
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
Describe the class of an AVClass context structure.
Definition: log.h:50
static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset, char **tracked_method)
Definition: rtmpproto.c:180
int index
Definition: gxfenc.c:89
synthesis window for stochastic i
int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type, int timestamp, int size)
Create new RTMP packet with given attributes.
Definition: rtmppkt.c:311
void * priv_data
Definition: url.h:44
int ff_rtmpe_update_keystream(URLContext *h)
Update the keystream and set RC4 keys for encryption.
Definition: rtmpcrypt.c:223
int ff_amf_read_number(GetByteContext *bc, double *val)
Read AMF number value.
Definition: rtmppkt.c:95
static int handle_notify(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1999
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:100
int channel_id
RTMP channel ID (nothing to do with audio/video channels though)
Definition: rtmppkt.h:78
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:30
uint8_t flv_header[11]
partial incoming flv packet header
Definition: rtmpproto.c:98
RTMPPacket out_pkt
rtmp packet, created from flv a/v or metadata (for output)
Definition: rtmpproto.c:93
#define snprintf
Definition: snprintf.h:34
char * tcurl
url of the target stream
Definition: rtmpproto.c:101
static int handle_connect_error(URLContext *s, const char *desc)
Definition: rtmpproto.c:1618
void av_md5_final(AVMD5 *ctx, uint8_t *dst)
Definition: md5.c:158
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
#define type
int listen
listen mode flag
Definition: rtmpproto.c:118
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes...
Definition: avstring.c:92
some notification
Definition: rtmppkt.h:58
static int rtmp_receive_hs_packet(RTMPContext *rt, uint32_t *first_int, uint32_t *second_int, char *arraydata, int size)
Definition: rtmpproto.c:1299
#define HMAC_IPAD_VAL
Definition: rtmp.h:32
track
Definition: brsc.py:18
static int flags
Definition: cpu.c:23
int ffurl_close(URLContext *h)
Definition: avio.c:359
#define SERVER_KEY_OPEN_PART_LEN
length of partial key used for first server digest signing
Definition: rtmpproto.c:139
channel for network-related messages (bandwidth report, ping, etc)
Definition: rtmppkt.h:37
static int gen_server_bw(URLContext *s, RTMPContext *rt)
Generate server bandwidth message and send it to the server.
Definition: rtmpproto.c:786
void ff_amf_write_null(uint8_t **dst)
Write AMF NULL value to buffer.
Definition: rtmppkt.c:63
uint32_t timestamp
packet full timestamp
Definition: rtmppkt.h:80
#define RTMP_HANDSHAKE_PACKET_SIZE
Definition: rtmp.h:30
#define FLASHVER_MAX_LENGTH
Definition: rtmpproto.c:56
uint8_t * data
packet payload
Definition: rtmppkt.h:83
Main libavformat public API header.
static int rtmp_open(URLContext *s, const char *uri, int flags)
Open RTMP connection and verify that the stream can be played.
Definition: rtmpproto.c:2260
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:162
int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
Change the position that will be used by the next read/write operation on the resource accessed by h...
Definition: avio.c:328
char * app
name of application
Definition: rtmpproto.c:85
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
Definition: avio.c:247
static double c[64]
int ffurl_read_complete(URLContext *h, unsigned char *buf, int size)
Read as many bytes as possible (up to size), calling the read function multiple times if necessary...
Definition: avio.c:310
static int rtmp_calc_swfhash(URLContext *s)
Definition: rtmpproto.c:1035
char * filename
specified URL
Definition: url.h:45
the buffer and buffer reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFilterBuffer structures They must not be accessed but through references stored in AVFilterBufferRef structures Several references can point to the same buffer
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
Definition: avio.h:222
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
channel for video data
Definition: rtmppkt.h:40
int ff_amf_read_string(GetByteContext *bc, uint8_t *str, int strsize, int *length)
Read AMF string value.
Definition: rtmppkt.c:105
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition: bytestream.h:337
int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket *prev_pkt, uint8_t hdr)
Read internal RTMP packet sent by the server.
Definition: rtmppkt.c:143
static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1740
void ff_amf_write_number(uint8_t **dst, double val)
Write number in AMF format to buffer.
Definition: rtmppkt.c:37
static const AVOption rtmp_options[]
Definition: rtmpproto.c:2633
static int get_packet(URLContext *s, int for_header)
Interact with the server by receiving and sending RTMP packets until there is some significant data (...
Definition: rtmpproto.c:2122
static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1873
int len
uint8_t * flv_data
buffer with data for demuxer
Definition: rtmpproto.c:89
else dst[i][x+y *dst_stride[i]]
Definition: vf_mcdeint.c:160
static int read_connect(URLContext *s, RTMPContext *rt)
Definition: rtmpproto.c:393
static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1500
#define RTMP_CLIENT_VER3
Definition: rtmp.h:42
void ff_amf_write_object_start(uint8_t **dst)
Write marker for AMF object to buffer.
Definition: rtmppkt.c:68
int do_reconnect
Definition: rtmpproto.c:124
#define RTMP_CLIENT_VER1
Definition: rtmp.h:40
int max_packet_size
if non zero, the stream is packetized with this max packet size
Definition: url.h:47
#define AV_LOG_INFO
Definition: log.h:156
protocol handler context
Definition: rtmpproto.c:76
struct TrackedMethod TrackedMethod
int swfsize
size of the decompressed SWF file
Definition: rtmpproto.c:105
structure for holding RTMP packets
Definition: rtmppkt.h:77
void ff_amf_write_string2(uint8_t **dst, const char *str1, const char *str2)
Write a string consisting of two parts in AMF format to a buffer.
Definition: rtmppkt.c:50
unbuffered private I/O API
invoke some stream action
Definition: rtmppkt.h:60
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
Definition: random_seed.c:105
static int handle_ping(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1449
char * ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase)
int ffurl_read(URLContext *h, unsigned char *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf...
Definition: avio.c:303
uint32_t client_report_size
number of bytes after which client should report to server
Definition: rtmpproto.c:94
int server_bw
server bandwidth
Definition: rtmpproto.c:111
FLV metadata.
Definition: rtmppkt.h:61
static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt, uint8_t *buf)
Definition: rtmpproto.c:967