FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtmpproto.c
Go to the documentation of this file.
1 /*
2  * RTMP network protocol
3  * Copyright (c) 2009 Konstantin 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 APP_MAX_LENGTH 1024
52 #define PLAYPATH_MAX_LENGTH 256
53 #define TCURL_MAX_LENGTH 512
54 #define FLASHVER_MAX_LENGTH 64
55 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
56 #define RTMP_HEADER 11
57 
58 /** RTMP protocol handler state */
59 typedef enum {
60  STATE_START, ///< client has not done anything yet
61  STATE_HANDSHAKED, ///< client has performed handshake
62  STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
63  STATE_PLAYING, ///< client has started receiving multimedia data from server
64  STATE_SEEKING, ///< client has started the seek operation. Back on STATE_PLAYING when the time comes
65  STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
66  STATE_RECEIVING, ///< received a publish command (for input)
67  STATE_SENDING, ///< received a play command (for output)
68  STATE_STOPPED, ///< the broadcast has been stopped
69 } ClientState;
70 
71 typedef struct TrackedMethod {
72  char *name;
73  int id;
75 
76 /** protocol handler context */
77 typedef struct RTMPContext {
78  const AVClass *class;
79  URLContext* stream; ///< TCP stream used in interactions with RTMP server
80  RTMPPacket *prev_pkt[2]; ///< packet history used when reading and sending packets ([0] for reading, [1] for writing)
81  int nb_prev_pkt[2]; ///< number of elements in prev_pkt
82  int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
83  int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
84  int is_input; ///< input/output flag
85  char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
86  int live; ///< 0: recorded, -1: live, -2: both
87  char *app; ///< name of application
88  char *conn; ///< append arbitrary AMF data to the Connect message
89  ClientState state; ///< current state
90  int stream_id; ///< ID assigned by the server for the stream
91  uint8_t* flv_data; ///< buffer with data for demuxer
92  int flv_size; ///< current buffer size
93  int flv_off; ///< number of bytes read from current buffer
94  int flv_nb_packets; ///< number of flv packets published
95  RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
96  uint32_t client_report_size; ///< number of bytes after which client should report to server
97  uint32_t bytes_read; ///< number of bytes read from server
98  uint32_t last_bytes_read; ///< number of bytes read last reported to server
99  uint32_t last_timestamp; ///< last timestamp received in a packet
100  int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
101  int has_audio; ///< presence of audio data
102  int has_video; ///< presence of video data
103  int received_metadata; ///< Indicates if we have received metadata about the streams
104  uint8_t flv_header[RTMP_HEADER]; ///< partial incoming flv packet header
105  int flv_header_bytes; ///< number of initialized bytes in flv_header
106  int nb_invokes; ///< keeps track of invoke messages
107  char* tcurl; ///< url of the target stream
108  char* flashver; ///< version of the flash plugin
109  char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
110  int swfhash_len; ///< length of the SHA256 hash
111  int swfsize; ///< size of the decompressed SWF file
112  char* swfurl; ///< url of the swf player
113  char* swfverify; ///< URL to player swf file, compute hash/size automatically
114  char swfverification[42]; ///< hash of the SWF verification
115  char* pageurl; ///< url of the web page
116  char* subscribe; ///< name of live stream to subscribe
117  int server_bw; ///< server bandwidth
118  int client_buffer_time; ///< client buffer time in ms
119  int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
120  int encrypted; ///< use an encrypted connection (RTMPE only)
121  TrackedMethod*tracked_methods; ///< tracked methods buffer
122  int nb_tracked_methods; ///< number of tracked methods
123  int tracked_methods_size; ///< size of the tracked methods buffer
124  int listen; ///< listen mode flag
125  int listen_timeout; ///< listen timeout to wait for new connections
126  int nb_streamid; ///< The next stream id to return on createStream calls
127  double duration; ///< Duration of the stream in seconds as returned by the server (only valid if non-zero)
128  char username[50];
129  char password[50];
130  char auth_params[500];
133 } RTMPContext;
134 
135 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
136 /** Client key used for digest signing */
137 static const uint8_t rtmp_player_key[] = {
138  'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
139  'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
140 
141  0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
142  0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
143  0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
144 };
145 
146 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
147 /** Key used for RTMP server digest signing */
148 static const uint8_t rtmp_server_key[] = {
149  'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
150  'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
151  'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
152 
153  0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
154  0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
155  0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
156 };
157 
159 
160 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
161 {
162  int err;
163 
164  if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
165  rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
166  if ((err = av_reallocp(&rt->tracked_methods, rt->tracked_methods_size *
167  sizeof(*rt->tracked_methods))) < 0) {
168  rt->nb_tracked_methods = 0;
169  rt->tracked_methods_size = 0;
170  return err;
171  }
172  }
173 
176  return AVERROR(ENOMEM);
178  rt->nb_tracked_methods++;
179 
180  return 0;
181 }
182 
183 static void del_tracked_method(RTMPContext *rt, int index)
184 {
185  memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
186  sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
187  rt->nb_tracked_methods--;
188 }
189 
191  char **tracked_method)
192 {
193  RTMPContext *rt = s->priv_data;
194  GetByteContext gbc;
195  double pkt_id;
196  int ret;
197  int i;
198 
199  bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset);
200  if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
201  return ret;
202 
203  for (i = 0; i < rt->nb_tracked_methods; i++) {
204  if (rt->tracked_methods[i].id != pkt_id)
205  continue;
206 
207  *tracked_method = rt->tracked_methods[i].name;
208  del_tracked_method(rt, i);
209  break;
210  }
211 
212  return 0;
213 }
214 
216 {
217  int i;
218 
219  for (i = 0; i < rt->nb_tracked_methods; i ++)
220  av_freep(&rt->tracked_methods[i].name);
222  rt->tracked_methods_size = 0;
223  rt->nb_tracked_methods = 0;
224 }
225 
226 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
227 {
228  int ret;
229 
230  if (pkt->type == RTMP_PT_INVOKE && track) {
231  GetByteContext gbc;
232  char name[128];
233  double pkt_id;
234  int len;
235 
236  bytestream2_init(&gbc, pkt->data, pkt->size);
237  if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
238  goto fail;
239 
240  if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
241  goto fail;
242 
243  if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
244  goto fail;
245  }
246 
247  ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
248  &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
249 fail:
251  return ret;
252 }
253 
254 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
255 {
256  char *field, *value;
257  char type;
258 
259  /* The type must be B for Boolean, N for number, S for string, O for
260  * object, or Z for null. For Booleans the data must be either 0 or 1 for
261  * FALSE or TRUE, respectively. Likewise for Objects the data must be
262  * 0 or 1 to end or begin an object, respectively. Data items in subobjects
263  * may be named, by prefixing the type with 'N' and specifying the name
264  * before the value (ie. NB:myFlag:1). This option may be used multiple times
265  * to construct arbitrary AMF sequences. */
266  if (param[0] && param[1] == ':') {
267  type = param[0];
268  value = param + 2;
269  } else if (param[0] == 'N' && param[1] && param[2] == ':') {
270  type = param[1];
271  field = param + 3;
272  value = strchr(field, ':');
273  if (!value)
274  goto fail;
275  *value = '\0';
276  value++;
277 
278  ff_amf_write_field_name(p, field);
279  } else {
280  goto fail;
281  }
282 
283  switch (type) {
284  case 'B':
285  ff_amf_write_bool(p, value[0] != '0');
286  break;
287  case 'S':
288  ff_amf_write_string(p, value);
289  break;
290  case 'N':
291  ff_amf_write_number(p, strtod(value, NULL));
292  break;
293  case 'Z':
295  break;
296  case 'O':
297  if (value[0] != '0')
299  else
301  break;
302  default:
303  goto fail;
304  break;
305  }
306 
307  return 0;
308 
309 fail:
310  av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
311  return AVERROR(EINVAL);
312 }
313 
314 /**
315  * Generate 'connect' call and send it to the server.
316  */
318 {
319  RTMPPacket pkt;
320  uint8_t *p;
321  int ret;
322 
324  0, 4096 + APP_MAX_LENGTH)) < 0)
325  return ret;
326 
327  p = pkt.data;
328 
329  ff_amf_write_string(&p, "connect");
330  ff_amf_write_number(&p, ++rt->nb_invokes);
332  ff_amf_write_field_name(&p, "app");
333  ff_amf_write_string2(&p, rt->app, rt->auth_params);
334 
335  if (!rt->is_input) {
336  ff_amf_write_field_name(&p, "type");
337  ff_amf_write_string(&p, "nonprivate");
338  }
339  ff_amf_write_field_name(&p, "flashVer");
340  ff_amf_write_string(&p, rt->flashver);
341 
342  if (rt->swfurl) {
343  ff_amf_write_field_name(&p, "swfUrl");
344  ff_amf_write_string(&p, rt->swfurl);
345  }
346 
347  ff_amf_write_field_name(&p, "tcUrl");
348  ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
349  if (rt->is_input) {
350  ff_amf_write_field_name(&p, "fpad");
351  ff_amf_write_bool(&p, 0);
352  ff_amf_write_field_name(&p, "capabilities");
353  ff_amf_write_number(&p, 15.0);
354 
355  /* Tell the server we support all the audio codecs except
356  * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
357  * which are unused in the RTMP protocol implementation. */
358  ff_amf_write_field_name(&p, "audioCodecs");
359  ff_amf_write_number(&p, 4071.0);
360  ff_amf_write_field_name(&p, "videoCodecs");
361  ff_amf_write_number(&p, 252.0);
362  ff_amf_write_field_name(&p, "videoFunction");
363  ff_amf_write_number(&p, 1.0);
364 
365  if (rt->pageurl) {
366  ff_amf_write_field_name(&p, "pageUrl");
367  ff_amf_write_string(&p, rt->pageurl);
368  }
369  }
371 
372  if (rt->conn) {
373  char *param = rt->conn;
374 
375  // Write arbitrary AMF data to the Connect message.
376  while (param) {
377  char *sep;
378  param += strspn(param, " ");
379  if (!*param)
380  break;
381  sep = strchr(param, ' ');
382  if (sep)
383  *sep = '\0';
384  if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
385  // Invalid AMF parameter.
387  return ret;
388  }
389 
390  if (sep)
391  param = sep + 1;
392  else
393  break;
394  }
395  }
396 
397  pkt.size = p - pkt.data;
398 
399  return rtmp_send_packet(rt, &pkt, 1);
400 }
401 
403 {
404  RTMPPacket pkt = { 0 };
405  uint8_t *p;
406  const uint8_t *cp;
407  int ret;
408  char command[64];
409  int stringlen;
410  double seqnum;
411  uint8_t tmpstr[256];
412  GetByteContext gbc;
413 
414  if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
415  &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
416  return ret;
417 
418  if (pkt.type == RTMP_PT_CHUNK_SIZE) {
419  if ((ret = handle_chunk_size(s, &pkt)) < 0)
420  return ret;
421 
423  if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
424  &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
425  return ret;
426  }
427 
428  cp = pkt.data;
429  bytestream2_init(&gbc, cp, pkt.size);
430  if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
431  av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
433  return AVERROR_INVALIDDATA;
434  }
435  if (strcmp(command, "connect")) {
436  av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
438  return AVERROR_INVALIDDATA;
439  }
440  ret = ff_amf_read_number(&gbc, &seqnum);
441  if (ret)
442  av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
443  /* Here one could parse an AMF Object with data as flashVers and others. */
444  ret = ff_amf_get_field_value(gbc.buffer,
446  "app", tmpstr, sizeof(tmpstr));
447  if (ret)
448  av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
449  if (!ret && strcmp(tmpstr, rt->app))
450  av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
451  tmpstr, rt->app);
453 
454  // Send Window Acknowledgement Size (as defined in speficication)
456  RTMP_PT_SERVER_BW, 0, 4)) < 0)
457  return ret;
458  p = pkt.data;
459  bytestream_put_be32(&p, rt->server_bw);
460  pkt.size = p - pkt.data;
461  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
462  &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
464  if (ret < 0)
465  return ret;
466  // Send Peer Bandwidth
468  RTMP_PT_CLIENT_BW, 0, 5)) < 0)
469  return ret;
470  p = pkt.data;
471  bytestream_put_be32(&p, rt->server_bw);
472  bytestream_put_byte(&p, 2); // dynamic
473  pkt.size = p - pkt.data;
474  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
475  &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
477  if (ret < 0)
478  return ret;
479 
480  // Ping request
482  RTMP_PT_PING, 0, 6)) < 0)
483  return ret;
484 
485  p = pkt.data;
486  bytestream_put_be16(&p, 0); // 0 -> Stream Begin
487  bytestream_put_be32(&p, 0);
488  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
489  &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
491  if (ret < 0)
492  return ret;
493 
494  // Chunk size
496  RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
497  return ret;
498 
499  p = pkt.data;
500  bytestream_put_be32(&p, rt->out_chunk_size);
501  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
502  &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
504  if (ret < 0)
505  return ret;
506 
507  // Send _result NetConnection.Connect.Success to connect
509  RTMP_PT_INVOKE, 0,
511  return ret;
512 
513  p = pkt.data;
514  ff_amf_write_string(&p, "_result");
515  ff_amf_write_number(&p, seqnum);
516 
518  ff_amf_write_field_name(&p, "fmsVer");
519  ff_amf_write_string(&p, "FMS/3,0,1,123");
520  ff_amf_write_field_name(&p, "capabilities");
521  ff_amf_write_number(&p, 31);
523 
525  ff_amf_write_field_name(&p, "level");
526  ff_amf_write_string(&p, "status");
527  ff_amf_write_field_name(&p, "code");
528  ff_amf_write_string(&p, "NetConnection.Connect.Success");
529  ff_amf_write_field_name(&p, "description");
530  ff_amf_write_string(&p, "Connection succeeded.");
531  ff_amf_write_field_name(&p, "objectEncoding");
532  ff_amf_write_number(&p, 0);
534 
535  pkt.size = p - pkt.data;
536  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
537  &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
539  if (ret < 0)
540  return ret;
541 
543  RTMP_PT_INVOKE, 0, 30)) < 0)
544  return ret;
545  p = pkt.data;
546  ff_amf_write_string(&p, "onBWDone");
547  ff_amf_write_number(&p, 0);
548  ff_amf_write_null(&p);
549  ff_amf_write_number(&p, 8192);
550  pkt.size = p - pkt.data;
551  ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
552  &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
554 
555  return ret;
556 }
557 
558 /**
559  * Generate 'releaseStream' call and send it to the server. It should make
560  * the server release some channel for media streams.
561  */
563 {
564  RTMPPacket pkt;
565  uint8_t *p;
566  int ret;
567 
569  0, 29 + strlen(rt->playpath))) < 0)
570  return ret;
571 
572  av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
573  p = pkt.data;
574  ff_amf_write_string(&p, "releaseStream");
575  ff_amf_write_number(&p, ++rt->nb_invokes);
576  ff_amf_write_null(&p);
577  ff_amf_write_string(&p, rt->playpath);
578 
579  return rtmp_send_packet(rt, &pkt, 1);
580 }
581 
582 /**
583  * Generate 'FCPublish' call and send it to the server. It should make
584  * the server preapare for receiving media streams.
585  */
587 {
588  RTMPPacket pkt;
589  uint8_t *p;
590  int ret;
591 
593  0, 25 + strlen(rt->playpath))) < 0)
594  return ret;
595 
596  av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
597  p = pkt.data;
598  ff_amf_write_string(&p, "FCPublish");
599  ff_amf_write_number(&p, ++rt->nb_invokes);
600  ff_amf_write_null(&p);
601  ff_amf_write_string(&p, rt->playpath);
602 
603  return rtmp_send_packet(rt, &pkt, 1);
604 }
605 
606 /**
607  * Generate 'FCUnpublish' call and send it to the server. It should make
608  * the server destroy stream.
609  */
611 {
612  RTMPPacket pkt;
613  uint8_t *p;
614  int ret;
615 
617  0, 27 + strlen(rt->playpath))) < 0)
618  return ret;
619 
620  av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
621  p = pkt.data;
622  ff_amf_write_string(&p, "FCUnpublish");
623  ff_amf_write_number(&p, ++rt->nb_invokes);
624  ff_amf_write_null(&p);
625  ff_amf_write_string(&p, rt->playpath);
626 
627  return rtmp_send_packet(rt, &pkt, 0);
628 }
629 
630 /**
631  * Generate 'createStream' call and send it to the server. It should make
632  * the server allocate some channel for media streams.
633  */
635 {
636  RTMPPacket pkt;
637  uint8_t *p;
638  int ret;
639 
640  av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
641 
643  0, 25)) < 0)
644  return ret;
645 
646  p = pkt.data;
647  ff_amf_write_string(&p, "createStream");
648  ff_amf_write_number(&p, ++rt->nb_invokes);
649  ff_amf_write_null(&p);
650 
651  return rtmp_send_packet(rt, &pkt, 1);
652 }
653 
654 
655 /**
656  * Generate 'deleteStream' call and send it to the server. It should make
657  * the server remove some channel for media streams.
658  */
660 {
661  RTMPPacket pkt;
662  uint8_t *p;
663  int ret;
664 
665  av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
666 
668  0, 34)) < 0)
669  return ret;
670 
671  p = pkt.data;
672  ff_amf_write_string(&p, "deleteStream");
673  ff_amf_write_number(&p, ++rt->nb_invokes);
674  ff_amf_write_null(&p);
676 
677  return rtmp_send_packet(rt, &pkt, 0);
678 }
679 
680 /**
681  * Generate 'getStreamLength' call and send it to the server. If the server
682  * knows the duration of the selected stream, it will reply with the duration
683  * in seconds.
684  */
686 {
687  RTMPPacket pkt;
688  uint8_t *p;
689  int ret;
690 
692  0, 31 + strlen(rt->playpath))) < 0)
693  return ret;
694 
695  p = pkt.data;
696  ff_amf_write_string(&p, "getStreamLength");
697  ff_amf_write_number(&p, ++rt->nb_invokes);
698  ff_amf_write_null(&p);
699  ff_amf_write_string(&p, rt->playpath);
700 
701  return rtmp_send_packet(rt, &pkt, 1);
702 }
703 
704 /**
705  * Generate client buffer time and send it to the server.
706  */
708 {
709  RTMPPacket pkt;
710  uint8_t *p;
711  int ret;
712 
714  1, 10)) < 0)
715  return ret;
716 
717  p = pkt.data;
718  bytestream_put_be16(&p, 3);
719  bytestream_put_be32(&p, rt->stream_id);
720  bytestream_put_be32(&p, rt->client_buffer_time);
721 
722  return rtmp_send_packet(rt, &pkt, 0);
723 }
724 
725 /**
726  * Generate 'play' call and send it to the server, then ping the server
727  * to start actual playing.
728  */
729 static int gen_play(URLContext *s, RTMPContext *rt)
730 {
731  RTMPPacket pkt;
732  uint8_t *p;
733  int ret;
734 
735  av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
736 
738  0, 29 + strlen(rt->playpath))) < 0)
739  return ret;
740 
741  pkt.extra = rt->stream_id;
742 
743  p = pkt.data;
744  ff_amf_write_string(&p, "play");
745  ff_amf_write_number(&p, ++rt->nb_invokes);
746  ff_amf_write_null(&p);
747  ff_amf_write_string(&p, rt->playpath);
748  ff_amf_write_number(&p, rt->live * 1000);
749 
750  return rtmp_send_packet(rt, &pkt, 1);
751 }
752 
753 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
754 {
755  RTMPPacket pkt;
756  uint8_t *p;
757  int ret;
758 
759  av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
760  timestamp);
761 
762  if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
763  return ret;
764 
765  pkt.extra = rt->stream_id;
766 
767  p = pkt.data;
768  ff_amf_write_string(&p, "seek");
769  ff_amf_write_number(&p, 0); //no tracking back responses
770  ff_amf_write_null(&p); //as usual, the first null param
771  ff_amf_write_number(&p, timestamp); //where we want to jump
772 
773  return rtmp_send_packet(rt, &pkt, 1);
774 }
775 
776 /**
777  * Generate a pause packet that either pauses or unpauses the current stream.
778  */
779 static int gen_pause(URLContext *s, RTMPContext *rt, int pause, uint32_t timestamp)
780 {
781  RTMPPacket pkt;
782  uint8_t *p;
783  int ret;
784 
785  av_log(s, AV_LOG_DEBUG, "Sending pause command for timestamp %d\n",
786  timestamp);
787 
788  if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 29)) < 0)
789  return ret;
790 
791  pkt.extra = rt->stream_id;
792 
793  p = pkt.data;
794  ff_amf_write_string(&p, "pause");
795  ff_amf_write_number(&p, 0); //no tracking back responses
796  ff_amf_write_null(&p); //as usual, the first null param
797  ff_amf_write_bool(&p, pause); // pause or unpause
798  ff_amf_write_number(&p, timestamp); //where we pause the stream
799 
800  return rtmp_send_packet(rt, &pkt, 1);
801 }
802 
803 /**
804  * Generate 'publish' call and send it to the server.
805  */
807 {
808  RTMPPacket pkt;
809  uint8_t *p;
810  int ret;
811 
812  av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
813 
815  0, 30 + strlen(rt->playpath))) < 0)
816  return ret;
817 
818  pkt.extra = rt->stream_id;
819 
820  p = pkt.data;
821  ff_amf_write_string(&p, "publish");
822  ff_amf_write_number(&p, ++rt->nb_invokes);
823  ff_amf_write_null(&p);
824  ff_amf_write_string(&p, rt->playpath);
825  ff_amf_write_string(&p, "live");
826 
827  return rtmp_send_packet(rt, &pkt, 1);
828 }
829 
830 /**
831  * Generate ping reply and send it to the server.
832  */
833 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
834 {
835  RTMPPacket pkt;
836  uint8_t *p;
837  int ret;
838 
839  if (ppkt->size < 6) {
840  av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
841  ppkt->size);
842  return AVERROR_INVALIDDATA;
843  }
844 
846  ppkt->timestamp + 1, 6)) < 0)
847  return ret;
848 
849  p = pkt.data;
850  bytestream_put_be16(&p, 7);
851  bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
852 
853  return rtmp_send_packet(rt, &pkt, 0);
854 }
855 
856 /**
857  * Generate SWF verification message and send it to the server.
858  */
860 {
861  RTMPPacket pkt;
862  uint8_t *p;
863  int ret;
864 
865  av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
867  0, 44)) < 0)
868  return ret;
869 
870  p = pkt.data;
871  bytestream_put_be16(&p, 27);
872  memcpy(p, rt->swfverification, 42);
873 
874  return rtmp_send_packet(rt, &pkt, 0);
875 }
876 
877 /**
878  * Generate server bandwidth message and send it to the server.
879  */
881 {
882  RTMPPacket pkt;
883  uint8_t *p;
884  int ret;
885 
887  0, 4)) < 0)
888  return ret;
889 
890  p = pkt.data;
891  bytestream_put_be32(&p, rt->server_bw);
892 
893  return rtmp_send_packet(rt, &pkt, 0);
894 }
895 
896 /**
897  * Generate check bandwidth message and send it to the server.
898  */
900 {
901  RTMPPacket pkt;
902  uint8_t *p;
903  int ret;
904 
906  0, 21)) < 0)
907  return ret;
908 
909  p = pkt.data;
910  ff_amf_write_string(&p, "_checkbw");
911  ff_amf_write_number(&p, ++rt->nb_invokes);
912  ff_amf_write_null(&p);
913 
914  return rtmp_send_packet(rt, &pkt, 1);
915 }
916 
917 /**
918  * Generate report on bytes read so far and send it to the server.
919  */
920 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
921 {
922  RTMPPacket pkt;
923  uint8_t *p;
924  int ret;
925 
927  ts, 4)) < 0)
928  return ret;
929 
930  p = pkt.data;
931  bytestream_put_be32(&p, rt->bytes_read);
932 
933  return rtmp_send_packet(rt, &pkt, 0);
934 }
935 
937  const char *subscribe)
938 {
939  RTMPPacket pkt;
940  uint8_t *p;
941  int ret;
942 
944  0, 27 + strlen(subscribe))) < 0)
945  return ret;
946 
947  p = pkt.data;
948  ff_amf_write_string(&p, "FCSubscribe");
949  ff_amf_write_number(&p, ++rt->nb_invokes);
950  ff_amf_write_null(&p);
951  ff_amf_write_string(&p, subscribe);
952 
953  return rtmp_send_packet(rt, &pkt, 1);
954 }
955 
956 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
957  const uint8_t *key, int keylen, uint8_t *dst)
958 {
959  struct AVSHA *sha;
960  uint8_t hmac_buf[64+32] = {0};
961  int i;
962 
963  sha = av_sha_alloc();
964  if (!sha)
965  return AVERROR(ENOMEM);
966 
967  if (keylen < 64) {
968  memcpy(hmac_buf, key, keylen);
969  } else {
970  av_sha_init(sha, 256);
971  av_sha_update(sha,key, keylen);
972  av_sha_final(sha, hmac_buf);
973  }
974  for (i = 0; i < 64; i++)
975  hmac_buf[i] ^= HMAC_IPAD_VAL;
976 
977  av_sha_init(sha, 256);
978  av_sha_update(sha, hmac_buf, 64);
979  if (gap <= 0) {
980  av_sha_update(sha, src, len);
981  } else { //skip 32 bytes used for storing digest
982  av_sha_update(sha, src, gap);
983  av_sha_update(sha, src + gap + 32, len - gap - 32);
984  }
985  av_sha_final(sha, hmac_buf + 64);
986 
987  for (i = 0; i < 64; i++)
988  hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
989  av_sha_init(sha, 256);
990  av_sha_update(sha, hmac_buf, 64+32);
991  av_sha_final(sha, dst);
992 
993  av_free(sha);
994 
995  return 0;
996 }
997 
998 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
999  int add_val)
1000 {
1001  int i, digest_pos = 0;
1002 
1003  for (i = 0; i < 4; i++)
1004  digest_pos += buf[i + off];
1005  digest_pos = digest_pos % mod_val + add_val;
1006 
1007  return digest_pos;
1008 }
1009 
1010 /**
1011  * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
1012  * will be stored) into that packet.
1013  *
1014  * @param buf handshake data (1536 bytes)
1015  * @param encrypted use an encrypted connection (RTMPE)
1016  * @return offset to the digest inside input data
1017  */
1019 {
1020  int ret, digest_pos;
1021 
1022  if (encrypted)
1023  digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
1024  else
1025  digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
1026 
1027  ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
1029  buf + digest_pos);
1030  if (ret < 0)
1031  return ret;
1032 
1033  return digest_pos;
1034 }
1035 
1036 /**
1037  * Verify that the received server response has the expected digest value.
1038  *
1039  * @param buf handshake data received from the server (1536 bytes)
1040  * @param off position to search digest offset from
1041  * @return 0 if digest is valid, digest position otherwise
1042  */
1043 static int rtmp_validate_digest(uint8_t *buf, int off)
1044 {
1045  uint8_t digest[32];
1046  int ret, digest_pos;
1047 
1048  digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
1049 
1050  ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
1052  digest);
1053  if (ret < 0)
1054  return ret;
1055 
1056  if (!memcmp(digest, buf + digest_pos, 32))
1057  return digest_pos;
1058  return 0;
1059 }
1060 
1062  uint8_t *buf)
1063 {
1064  uint8_t *p;
1065  int ret;
1066 
1067  if (rt->swfhash_len != 32) {
1068  av_log(s, AV_LOG_ERROR,
1069  "Hash of the decompressed SWF file is not 32 bytes long.\n");
1070  return AVERROR(EINVAL);
1071  }
1072 
1073  p = &rt->swfverification[0];
1074  bytestream_put_byte(&p, 1);
1075  bytestream_put_byte(&p, 1);
1076  bytestream_put_be32(&p, rt->swfsize);
1077  bytestream_put_be32(&p, rt->swfsize);
1078 
1079  if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1080  return ret;
1081 
1082  return 0;
1083 }
1084 
1085 #if CONFIG_ZLIB
1086 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1087  uint8_t **out_data, int64_t *out_size)
1088 {
1089  z_stream zs = { 0 };
1090  void *ptr;
1091  int size;
1092  int ret = 0;
1093 
1094  zs.avail_in = in_size;
1095  zs.next_in = in_data;
1096  ret = inflateInit(&zs);
1097  if (ret != Z_OK)
1098  return AVERROR_UNKNOWN;
1099 
1100  do {
1101  uint8_t tmp_buf[16384];
1102 
1103  zs.avail_out = sizeof(tmp_buf);
1104  zs.next_out = tmp_buf;
1105 
1106  ret = inflate(&zs, Z_NO_FLUSH);
1107  if (ret != Z_OK && ret != Z_STREAM_END) {
1108  ret = AVERROR_UNKNOWN;
1109  goto fail;
1110  }
1111 
1112  size = sizeof(tmp_buf) - zs.avail_out;
1113  if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1114  ret = AVERROR(ENOMEM);
1115  goto fail;
1116  }
1117  *out_data = ptr;
1118 
1119  memcpy(*out_data + *out_size, tmp_buf, size);
1120  *out_size += size;
1121  } while (zs.avail_out == 0);
1122 
1123 fail:
1124  inflateEnd(&zs);
1125  return ret;
1126 }
1127 #endif
1128 
1130 {
1131  RTMPContext *rt = s->priv_data;
1132  uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1133  int64_t in_size, out_size;
1134  URLContext *stream;
1135  char swfhash[32];
1136  int swfsize;
1137  int ret = 0;
1138 
1139  /* Get the SWF player file. */
1140  if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1141  &s->interrupt_callback, NULL)) < 0) {
1142  av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1143  goto fail;
1144  }
1145 
1146  if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1147  ret = AVERROR(EIO);
1148  goto fail;
1149  }
1150 
1151  if (!(in_data = av_malloc(in_size))) {
1152  ret = AVERROR(ENOMEM);
1153  goto fail;
1154  }
1155 
1156  if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1157  goto fail;
1158 
1159  if (in_size < 3) {
1160  ret = AVERROR_INVALIDDATA;
1161  goto fail;
1162  }
1163 
1164  if (!memcmp(in_data, "CWS", 3)) {
1165  /* Decompress the SWF player file using Zlib. */
1166  if (!(out_data = av_malloc(8))) {
1167  ret = AVERROR(ENOMEM);
1168  goto fail;
1169  }
1170  *in_data = 'F'; // magic stuff
1171  memcpy(out_data, in_data, 8);
1172  out_size = 8;
1173 
1174 #if CONFIG_ZLIB
1175  if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1176  &out_data, &out_size)) < 0)
1177  goto fail;
1178 #else
1179  av_log(s, AV_LOG_ERROR,
1180  "Zlib is required for decompressing the SWF player file.\n");
1181  ret = AVERROR(EINVAL);
1182  goto fail;
1183 #endif
1184  swfsize = out_size;
1185  swfdata = out_data;
1186  } else {
1187  swfsize = in_size;
1188  swfdata = in_data;
1189  }
1190 
1191  /* Compute the SHA256 hash of the SWF player file. */
1192  if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1193  "Genuine Adobe Flash Player 001", 30,
1194  swfhash)) < 0)
1195  goto fail;
1196 
1197  /* Set SWFVerification parameters. */
1198  av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1199  rt->swfsize = swfsize;
1200 
1201 fail:
1202  av_freep(&in_data);
1203  av_freep(&out_data);
1204  ffurl_close(stream);
1205  return ret;
1206 }
1207 
1208 /**
1209  * Perform handshake with the server by means of exchanging pseudorandom data
1210  * signed with HMAC-SHA2 digest.
1211  *
1212  * @return 0 if handshake succeeds, negative value otherwise
1213  */
1215 {
1216  AVLFG rnd;
1217  uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1218  3, // unencrypted data
1219  0, 0, 0, 0, // client uptime
1224  };
1225  uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1226  uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1227  int i;
1228  int server_pos, client_pos;
1229  uint8_t digest[32], signature[32];
1230  int ret, type = 0;
1231 
1232  av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1233 
1234  av_lfg_init(&rnd, 0xDEADC0DE);
1235  // generate handshake packet - 1536 bytes of pseudorandom data
1236  for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1237  tosend[i] = av_lfg_get(&rnd) >> 24;
1238 
1239  if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1240  /* When the client wants to use RTMPE, we have to change the command
1241  * byte to 0x06 which means to use encrypted data and we have to set
1242  * the flash version to at least 9.0.115.0. */
1243  tosend[0] = 6;
1244  tosend[5] = 128;
1245  tosend[6] = 0;
1246  tosend[7] = 3;
1247  tosend[8] = 2;
1248 
1249  /* Initialize the Diffie-Hellmann context and generate the public key
1250  * to send to the server. */
1251  if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1252  return ret;
1253  }
1254 
1255  client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1256  if (client_pos < 0)
1257  return client_pos;
1258 
1259  if ((ret = ffurl_write(rt->stream, tosend,
1260  RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1261  av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1262  return ret;
1263  }
1264 
1265  if ((ret = ffurl_read_complete(rt->stream, serverdata,
1266  RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1267  av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1268  return ret;
1269  }
1270 
1271  if ((ret = ffurl_read_complete(rt->stream, clientdata,
1273  av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1274  return ret;
1275  }
1276 
1277  av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1278  av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1279  serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1280 
1281  if (rt->is_input && serverdata[5] >= 3) {
1282  server_pos = rtmp_validate_digest(serverdata + 1, 772);
1283  if (server_pos < 0)
1284  return server_pos;
1285 
1286  if (!server_pos) {
1287  type = 1;
1288  server_pos = rtmp_validate_digest(serverdata + 1, 8);
1289  if (server_pos < 0)
1290  return server_pos;
1291 
1292  if (!server_pos) {
1293  av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1294  return AVERROR(EIO);
1295  }
1296  }
1297 
1298  /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1299  * key are the last 32 bytes of the server handshake. */
1300  if (rt->swfsize) {
1301  if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1302  RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1303  return ret;
1304  }
1305 
1306  ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1308  digest);
1309  if (ret < 0)
1310  return ret;
1311 
1312  ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1313  0, digest, 32, signature);
1314  if (ret < 0)
1315  return ret;
1316 
1317  if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1318  /* Compute the shared secret key sent by the server and initialize
1319  * the RC4 encryption. */
1320  if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1321  tosend + 1, type)) < 0)
1322  return ret;
1323 
1324  /* Encrypt the signature received by the server. */
1325  ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1326  }
1327 
1328  if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1329  av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1330  return AVERROR(EIO);
1331  }
1332 
1333  for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1334  tosend[i] = av_lfg_get(&rnd) >> 24;
1335  ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1337  digest);
1338  if (ret < 0)
1339  return ret;
1340 
1341  ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1342  digest, 32,
1343  tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1344  if (ret < 0)
1345  return ret;
1346 
1347  if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1348  /* Encrypt the signature to be send to the server. */
1349  ff_rtmpe_encrypt_sig(rt->stream, tosend +
1350  RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1351  serverdata[0]);
1352  }
1353 
1354  // write reply back to the server
1355  if ((ret = ffurl_write(rt->stream, tosend,
1356  RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1357  return ret;
1358 
1359  if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1360  /* Set RC4 keys for encryption and update the keystreams. */
1361  if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1362  return ret;
1363  }
1364  } else {
1365  if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1366  /* Compute the shared secret key sent by the server and initialize
1367  * the RC4 encryption. */
1368  if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1369  tosend + 1, 1)) < 0)
1370  return ret;
1371 
1372  if (serverdata[0] == 9) {
1373  /* Encrypt the signature received by the server. */
1374  ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1375  serverdata[0]);
1376  }
1377  }
1378 
1379  if ((ret = ffurl_write(rt->stream, serverdata + 1,
1381  return ret;
1382 
1383  if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1384  /* Set RC4 keys for encryption and update the keystreams. */
1385  if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1386  return ret;
1387  }
1388  }
1389 
1390  return 0;
1391 }
1392 
1393 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1394  uint32_t *second_int, char *arraydata,
1395  int size)
1396 {
1397  int inoutsize;
1398 
1399  inoutsize = ffurl_read_complete(rt->stream, arraydata,
1401  if (inoutsize <= 0)
1402  return AVERROR(EIO);
1403  if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1404  av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1405  " not following standard\n", (int)inoutsize);
1406  return AVERROR(EINVAL);
1407  }
1408 
1409  *first_int = AV_RB32(arraydata);
1410  *second_int = AV_RB32(arraydata + 4);
1411  return 0;
1412 }
1413 
1414 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1415  uint32_t second_int, char *arraydata, int size)
1416 {
1417  int inoutsize;
1418 
1419  AV_WB32(arraydata, first_int);
1420  AV_WB32(arraydata + 4, second_int);
1421  inoutsize = ffurl_write(rt->stream, arraydata,
1423  if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1424  av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1425  return AVERROR(EIO);
1426  }
1427 
1428  return 0;
1429 }
1430 
1431 /**
1432  * rtmp handshake server side
1433  */
1435 {
1437  uint32_t hs_epoch;
1438  uint32_t hs_my_epoch;
1441  uint32_t zeroes;
1442  uint32_t temp = 0;
1443  int randomidx = 0;
1444  int inoutsize = 0;
1445  int ret;
1446 
1447  inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1448  if (inoutsize <= 0) {
1449  av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1450  return AVERROR(EIO);
1451  }
1452  // Check Version
1453  if (buffer[0] != 3) {
1454  av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1455  return AVERROR(EIO);
1456  }
1457  if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1458  av_log(s, AV_LOG_ERROR,
1459  "Unable to write answer - RTMP S0\n");
1460  return AVERROR(EIO);
1461  }
1462  /* Receive C1 */
1463  ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1465  if (ret) {
1466  av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1467  return ret;
1468  }
1469  /* Send S1 */
1470  /* By now same epoch will be sent */
1471  hs_my_epoch = hs_epoch;
1472  /* Generate random */
1473  for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1474  randomidx += 4)
1475  AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1476 
1477  ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1479  if (ret) {
1480  av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1481  return ret;
1482  }
1483  /* Send S2 */
1484  ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1486  if (ret) {
1487  av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1488  return ret;
1489  }
1490  /* Receive C2 */
1491  ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1493  if (ret) {
1494  av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1495  return ret;
1496  }
1497  if (temp != hs_my_epoch)
1499  "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1500  if (memcmp(buffer + 8, hs_s1 + 8,
1503  "Erroneous C2 Message random does not match up\n");
1504 
1505  return 0;
1506 }
1507 
1509 {
1510  RTMPContext *rt = s->priv_data;
1511  int ret;
1512 
1513  if (pkt->size < 4) {
1514  av_log(s, AV_LOG_ERROR,
1515  "Too short chunk size change packet (%d)\n",
1516  pkt->size);
1517  return AVERROR_INVALIDDATA;
1518  }
1519 
1520  if (!rt->is_input) {
1521  /* Send the same chunk size change packet back to the server,
1522  * setting the outgoing chunk size to the same as the incoming one. */
1523  if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1524  &rt->prev_pkt[1], &rt->nb_prev_pkt[1])) < 0)
1525  return ret;
1526  rt->out_chunk_size = AV_RB32(pkt->data);
1527  }
1528 
1529  rt->in_chunk_size = AV_RB32(pkt->data);
1530  if (rt->in_chunk_size <= 0) {
1531  av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1532  rt->in_chunk_size);
1533  return AVERROR_INVALIDDATA;
1534  }
1535  av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1536  rt->in_chunk_size);
1537 
1538  return 0;
1539 }
1540 
1542 {
1543  RTMPContext *rt = s->priv_data;
1544  int t, ret;
1545 
1546  if (pkt->size < 2) {
1547  av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1548  pkt->size);
1549  return AVERROR_INVALIDDATA;
1550  }
1551 
1552  t = AV_RB16(pkt->data);
1553  if (t == 6) {
1554  if ((ret = gen_pong(s, rt, pkt)) < 0)
1555  return ret;
1556  } else if (t == 26) {
1557  if (rt->swfsize) {
1558  if ((ret = gen_swf_verification(s, rt)) < 0)
1559  return ret;
1560  } else {
1561  av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1562  }
1563  }
1564 
1565  return 0;
1566 }
1567 
1569 {
1570  RTMPContext *rt = s->priv_data;
1571 
1572  if (pkt->size < 4) {
1573  av_log(s, AV_LOG_ERROR,
1574  "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1575  pkt->size);
1576  return AVERROR_INVALIDDATA;
1577  }
1578 
1579  rt->client_report_size = AV_RB32(pkt->data);
1580  if (rt->client_report_size <= 0) {
1581  av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1582  rt->client_report_size);
1583  return AVERROR_INVALIDDATA;
1584 
1585  }
1586  av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1587  rt->client_report_size >>= 1;
1588 
1589  return 0;
1590 }
1591 
1593 {
1594  RTMPContext *rt = s->priv_data;
1595 
1596  if (pkt->size < 4) {
1597  av_log(s, AV_LOG_ERROR,
1598  "Too short server bandwidth report packet (%d)\n",
1599  pkt->size);
1600  return AVERROR_INVALIDDATA;
1601  }
1602 
1603  rt->server_bw = AV_RB32(pkt->data);
1604  if (rt->server_bw <= 0) {
1605  av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1606  rt->server_bw);
1607  return AVERROR_INVALIDDATA;
1608  }
1609  av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1610 
1611  return 0;
1612 }
1613 
1614 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1615  const char *opaque, const char *challenge)
1616 {
1617  uint8_t hash[16];
1618  char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1619  struct AVMD5 *md5 = av_md5_alloc();
1620  if (!md5)
1621  return AVERROR(ENOMEM);
1622 
1623  snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1624 
1625  av_md5_init(md5);
1626  av_md5_update(md5, user, strlen(user));
1627  av_md5_update(md5, salt, strlen(salt));
1628  av_md5_update(md5, rt->password, strlen(rt->password));
1629  av_md5_final(md5, hash);
1630  av_base64_encode(hashstr, sizeof(hashstr), hash,
1631  sizeof(hash));
1632  av_md5_init(md5);
1633  av_md5_update(md5, hashstr, strlen(hashstr));
1634  if (opaque)
1635  av_md5_update(md5, opaque, strlen(opaque));
1636  else if (challenge)
1637  av_md5_update(md5, challenge, strlen(challenge));
1638  av_md5_update(md5, challenge2, strlen(challenge2));
1639  av_md5_final(md5, hash);
1640  av_base64_encode(hashstr, sizeof(hashstr), hash,
1641  sizeof(hash));
1642  snprintf(rt->auth_params, sizeof(rt->auth_params),
1643  "?authmod=%s&user=%s&challenge=%s&response=%s",
1644  "adobe", user, challenge2, hashstr);
1645  if (opaque)
1646  av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1647  "&opaque=%s", opaque);
1648 
1649  av_free(md5);
1650  return 0;
1651 }
1652 
1653 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1654 {
1655  uint8_t hash[16];
1656  char hashstr1[33], hashstr2[33];
1657  const char *realm = "live";
1658  const char *method = "publish";
1659  const char *qop = "auth";
1660  const char *nc = "00000001";
1661  char cnonce[10];
1662  struct AVMD5 *md5 = av_md5_alloc();
1663  if (!md5)
1664  return AVERROR(ENOMEM);
1665 
1666  snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1667 
1668  av_md5_init(md5);
1669  av_md5_update(md5, user, strlen(user));
1670  av_md5_update(md5, ":", 1);
1671  av_md5_update(md5, realm, strlen(realm));
1672  av_md5_update(md5, ":", 1);
1673  av_md5_update(md5, rt->password, strlen(rt->password));
1674  av_md5_final(md5, hash);
1675  ff_data_to_hex(hashstr1, hash, 16, 1);
1676  hashstr1[32] = '\0';
1677 
1678  av_md5_init(md5);
1679  av_md5_update(md5, method, strlen(method));
1680  av_md5_update(md5, ":/", 2);
1681  av_md5_update(md5, rt->app, strlen(rt->app));
1682  if (!strchr(rt->app, '/'))
1683  av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1684  av_md5_final(md5, hash);
1685  ff_data_to_hex(hashstr2, hash, 16, 1);
1686  hashstr2[32] = '\0';
1687 
1688  av_md5_init(md5);
1689  av_md5_update(md5, hashstr1, strlen(hashstr1));
1690  av_md5_update(md5, ":", 1);
1691  if (nonce)
1692  av_md5_update(md5, nonce, strlen(nonce));
1693  av_md5_update(md5, ":", 1);
1694  av_md5_update(md5, nc, strlen(nc));
1695  av_md5_update(md5, ":", 1);
1696  av_md5_update(md5, cnonce, strlen(cnonce));
1697  av_md5_update(md5, ":", 1);
1698  av_md5_update(md5, qop, strlen(qop));
1699  av_md5_update(md5, ":", 1);
1700  av_md5_update(md5, hashstr2, strlen(hashstr2));
1701  av_md5_final(md5, hash);
1702  ff_data_to_hex(hashstr1, hash, 16, 1);
1703 
1704  snprintf(rt->auth_params, sizeof(rt->auth_params),
1705  "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1706  "llnw", user, nonce, cnonce, nc, hashstr1);
1707 
1708  av_free(md5);
1709  return 0;
1710 }
1711 
1712 static int handle_connect_error(URLContext *s, const char *desc)
1713 {
1714  RTMPContext *rt = s->priv_data;
1715  char buf[300], *ptr, authmod[15];
1716  int i = 0, ret = 0;
1717  const char *user = "", *salt = "", *opaque = NULL,
1718  *challenge = NULL, *cptr = NULL, *nonce = NULL;
1719 
1720  if (!(cptr = strstr(desc, "authmod=adobe")) &&
1721  !(cptr = strstr(desc, "authmod=llnw"))) {
1722  av_log(s, AV_LOG_ERROR,
1723  "Unknown connect error (unsupported authentication method?)\n");
1724  return AVERROR_UNKNOWN;
1725  }
1726  cptr += strlen("authmod=");
1727  while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1728  authmod[i++] = *cptr++;
1729  authmod[i] = '\0';
1730 
1731  if (!rt->username[0] || !rt->password[0]) {
1732  av_log(s, AV_LOG_ERROR, "No credentials set\n");
1733  return AVERROR_UNKNOWN;
1734  }
1735 
1736  if (strstr(desc, "?reason=authfailed")) {
1737  av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1738  return AVERROR_UNKNOWN;
1739  } else if (strstr(desc, "?reason=nosuchuser")) {
1740  av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1741  return AVERROR_UNKNOWN;
1742  }
1743 
1744  if (rt->auth_tried) {
1745  av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1746  return AVERROR_UNKNOWN;
1747  }
1748 
1749  rt->auth_params[0] = '\0';
1750 
1751  if (strstr(desc, "code=403 need auth")) {
1752  snprintf(rt->auth_params, sizeof(rt->auth_params),
1753  "?authmod=%s&user=%s", authmod, rt->username);
1754  return 0;
1755  }
1756 
1757  if (!(cptr = strstr(desc, "?reason=needauth"))) {
1758  av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1759  return AVERROR_UNKNOWN;
1760  }
1761 
1762  av_strlcpy(buf, cptr + 1, sizeof(buf));
1763  ptr = buf;
1764 
1765  while (ptr) {
1766  char *next = strchr(ptr, '&');
1767  char *value = strchr(ptr, '=');
1768  if (next)
1769  *next++ = '\0';
1770  if (value) {
1771  *value++ = '\0';
1772  if (!strcmp(ptr, "user")) {
1773  user = value;
1774  } else if (!strcmp(ptr, "salt")) {
1775  salt = value;
1776  } else if (!strcmp(ptr, "opaque")) {
1777  opaque = value;
1778  } else if (!strcmp(ptr, "challenge")) {
1779  challenge = value;
1780  } else if (!strcmp(ptr, "nonce")) {
1781  nonce = value;
1782  } else {
1783  av_log(s, AV_LOG_INFO, "Ignoring unsupported var %s\n", ptr);
1784  }
1785  } else {
1786  av_log(s, AV_LOG_WARNING, "Variable %s has NULL value\n", ptr);
1787  }
1788  ptr = next;
1789  }
1790 
1791  if (!strcmp(authmod, "adobe")) {
1792  if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1793  return ret;
1794  } else {
1795  if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1796  return ret;
1797  }
1798 
1799  rt->auth_tried = 1;
1800  return 0;
1801 }
1802 
1804 {
1805  RTMPContext *rt = s->priv_data;
1806  const uint8_t *data_end = pkt->data + pkt->size;
1807  char *tracked_method = NULL;
1808  int level = AV_LOG_ERROR;
1809  uint8_t tmpstr[256];
1810  int ret;
1811 
1812  if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1813  return ret;
1814 
1815  if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1816  "description", tmpstr, sizeof(tmpstr))) {
1817  if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1818  !strcmp(tracked_method, "releaseStream") ||
1819  !strcmp(tracked_method, "FCSubscribe") ||
1820  !strcmp(tracked_method, "FCPublish"))) {
1821  /* Gracefully ignore Adobe-specific historical artifact errors. */
1822  level = AV_LOG_WARNING;
1823  ret = 0;
1824  } else if (tracked_method && !strcmp(tracked_method, "getStreamLength")) {
1825  level = rt->live ? AV_LOG_DEBUG : AV_LOG_WARNING;
1826  ret = 0;
1827  } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1828  ret = handle_connect_error(s, tmpstr);
1829  if (!ret) {
1830  rt->do_reconnect = 1;
1831  level = AV_LOG_VERBOSE;
1832  }
1833  } else
1834  ret = AVERROR_UNKNOWN;
1835  av_log(s, level, "Server error: %s\n", tmpstr);
1836  }
1837 
1838  av_free(tracked_method);
1839  return ret;
1840 }
1841 
1843 {
1844  RTMPContext *rt = s->priv_data;
1845  PutByteContext pbc;
1846  RTMPPacket spkt = { 0 };
1847  int ret;
1848 
1849  // Send Stream Begin 1
1850  if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1851  RTMP_PT_PING, 0, 6)) < 0) {
1852  av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1853  return ret;
1854  }
1855 
1856  bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1857  bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1858  bytestream2_put_be32(&pbc, rt->nb_streamid);
1859 
1860  ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1861  &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1862 
1863  ff_rtmp_packet_destroy(&spkt);
1864 
1865  return ret;
1866 }
1867 
1869  const char *status, const char *filename)
1870 {
1871  RTMPContext *rt = s->priv_data;
1872  RTMPPacket spkt = { 0 };
1873  char statusmsg[128];
1874  uint8_t *pp;
1875  int ret;
1876 
1877  if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1878  RTMP_PT_INVOKE, 0,
1879  RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1880  av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1881  return ret;
1882  }
1883 
1884  pp = spkt.data;
1885  spkt.extra = pkt->extra;
1886  ff_amf_write_string(&pp, "onStatus");
1887  ff_amf_write_number(&pp, 0);
1888  ff_amf_write_null(&pp);
1889 
1891  ff_amf_write_field_name(&pp, "level");
1892  ff_amf_write_string(&pp, "status");
1893  ff_amf_write_field_name(&pp, "code");
1894  ff_amf_write_string(&pp, status);
1895  ff_amf_write_field_name(&pp, "description");
1896  snprintf(statusmsg, sizeof(statusmsg),
1897  "%s is now published", filename);
1898  ff_amf_write_string(&pp, statusmsg);
1899  ff_amf_write_field_name(&pp, "details");
1900  ff_amf_write_string(&pp, filename);
1901  ff_amf_write_field_name(&pp, "clientid");
1902  snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1903  ff_amf_write_string(&pp, statusmsg);
1905 
1906  spkt.size = pp - spkt.data;
1907  ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1908  &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1909  ff_rtmp_packet_destroy(&spkt);
1910 
1911  return ret;
1912 }
1913 
1915 {
1916  RTMPContext *rt = s->priv_data;
1917  double seqnum;
1918  char filename[64];
1919  char command[64];
1920  int stringlen;
1921  char *pchar;
1922  const uint8_t *p = pkt->data;
1923  uint8_t *pp = NULL;
1924  RTMPPacket spkt = { 0 };
1925  GetByteContext gbc;
1926  int ret;
1927 
1928  bytestream2_init(&gbc, p, pkt->size);
1929  if (ff_amf_read_string(&gbc, command, sizeof(command),
1930  &stringlen)) {
1931  av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1932  return AVERROR_INVALIDDATA;
1933  }
1934 
1935  ret = ff_amf_read_number(&gbc, &seqnum);
1936  if (ret)
1937  return ret;
1938  ret = ff_amf_read_null(&gbc);
1939  if (ret)
1940  return ret;
1941  if (!strcmp(command, "FCPublish") ||
1942  !strcmp(command, "publish")) {
1943  ret = ff_amf_read_string(&gbc, filename,
1944  sizeof(filename), &stringlen);
1945  // check with url
1946  if (s->filename) {
1947  pchar = strrchr(s->filename, '/');
1948  if (!pchar) {
1950  "Unable to find / in url %s, bad format\n",
1951  s->filename);
1952  pchar = s->filename;
1953  }
1954  pchar++;
1955  if (strcmp(pchar, filename))
1956  av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1957  " %s\n", filename, pchar);
1958  }
1959  rt->state = STATE_RECEIVING;
1960  }
1961 
1962  if (!strcmp(command, "FCPublish")) {
1963  if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1964  RTMP_PT_INVOKE, 0,
1965  RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1966  av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1967  return ret;
1968  }
1969  pp = spkt.data;
1970  ff_amf_write_string(&pp, "onFCPublish");
1971  } else if (!strcmp(command, "publish")) {
1972  ret = write_begin(s);
1973  if (ret < 0)
1974  return ret;
1975 
1976  // Send onStatus(NetStream.Publish.Start)
1977  return write_status(s, pkt, "NetStream.Publish.Start",
1978  filename);
1979  } else if (!strcmp(command, "play")) {
1980  ret = write_begin(s);
1981  if (ret < 0)
1982  return ret;
1983  rt->state = STATE_SENDING;
1984  return write_status(s, pkt, "NetStream.Play.Start",
1985  filename);
1986  } else {
1987  if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1988  RTMP_PT_INVOKE, 0,
1989  RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1990  av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1991  return ret;
1992  }
1993  pp = spkt.data;
1994  ff_amf_write_string(&pp, "_result");
1995  ff_amf_write_number(&pp, seqnum);
1996  ff_amf_write_null(&pp);
1997  if (!strcmp(command, "createStream")) {
1998  rt->nb_streamid++;
1999  if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
2000  rt->nb_streamid++; /* Values 0 and 2 are reserved */
2001  ff_amf_write_number(&pp, rt->nb_streamid);
2002  /* By now we don't control which streams are removed in
2003  * deleteStream. There is no stream creation control
2004  * if a client creates more than 2^32 - 2 streams. */
2005  }
2006  }
2007  spkt.size = pp - spkt.data;
2008  ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
2009  &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
2010  ff_rtmp_packet_destroy(&spkt);
2011  return ret;
2012 }
2013 
2014 /**
2015  * Read the AMF_NUMBER response ("_result") to a function call
2016  * (e.g. createStream()). This response should be made up of the AMF_STRING
2017  * "result", a NULL object and then the response encoded as AMF_NUMBER. On a
2018  * successful response, we will return set the value to number (otherwise number
2019  * will not be changed).
2020  *
2021  * @return 0 if reading the value succeeds, negative value otherwiss
2022  */
2023 static int read_number_result(RTMPPacket *pkt, double *number)
2024 {
2025  // We only need to fit "_result" in this.
2026  uint8_t strbuffer[8];
2027  int stringlen;
2028  double numbuffer;
2029  GetByteContext gbc;
2030 
2031  bytestream2_init(&gbc, pkt->data, pkt->size);
2032 
2033  // Value 1/4: "_result" as AMF_STRING
2034  if (ff_amf_read_string(&gbc, strbuffer, sizeof(strbuffer), &stringlen))
2035  return AVERROR_INVALIDDATA;
2036  if (strcmp(strbuffer, "_result"))
2037  return AVERROR_INVALIDDATA;
2038  // Value 2/4: The callee reference number
2039  if (ff_amf_read_number(&gbc, &numbuffer))
2040  return AVERROR_INVALIDDATA;
2041  // Value 3/4: Null
2042  if (ff_amf_read_null(&gbc))
2043  return AVERROR_INVALIDDATA;
2044  // Value 4/4: The resonse as AMF_NUMBER
2045  if (ff_amf_read_number(&gbc, &numbuffer))
2046  return AVERROR_INVALIDDATA;
2047  else
2048  *number = numbuffer;
2049 
2050  return 0;
2051 }
2052 
2054 {
2055  RTMPContext *rt = s->priv_data;
2056  char *tracked_method = NULL;
2057  int ret = 0;
2058 
2059  if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
2060  return ret;
2061 
2062  if (!tracked_method) {
2063  /* Ignore this reply when the current method is not tracked. */
2064  return ret;
2065  }
2066 
2067  if (!strcmp(tracked_method, "connect")) {
2068  if (!rt->is_input) {
2069  if ((ret = gen_release_stream(s, rt)) < 0)
2070  goto fail;
2071 
2072  if ((ret = gen_fcpublish_stream(s, rt)) < 0)
2073  goto fail;
2074  } else {
2075  if ((ret = gen_server_bw(s, rt)) < 0)
2076  goto fail;
2077  }
2078 
2079  if ((ret = gen_create_stream(s, rt)) < 0)
2080  goto fail;
2081 
2082  if (rt->is_input) {
2083  /* Send the FCSubscribe command when the name of live
2084  * stream is defined by the user or if it's a live stream. */
2085  if (rt->subscribe) {
2086  if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
2087  goto fail;
2088  } else if (rt->live == -1) {
2089  if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
2090  goto fail;
2091  }
2092  }
2093  } else if (!strcmp(tracked_method, "createStream")) {
2094  double stream_id;
2095  if (read_number_result(pkt, &stream_id)) {
2096  av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
2097  } else {
2098  rt->stream_id = stream_id;
2099  }
2100 
2101  if (!rt->is_input) {
2102  if ((ret = gen_publish(s, rt)) < 0)
2103  goto fail;
2104  } else {
2105  if (rt->live != -1) {
2106  if ((ret = gen_get_stream_length(s, rt)) < 0)
2107  goto fail;
2108  }
2109  if ((ret = gen_play(s, rt)) < 0)
2110  goto fail;
2111  if ((ret = gen_buffer_time(s, rt)) < 0)
2112  goto fail;
2113  }
2114  } else if (!strcmp(tracked_method, "getStreamLength")) {
2115  if (read_number_result(pkt, &rt->duration)) {
2116  av_log(s, AV_LOG_WARNING, "Unexpected reply on getStreamLength()\n");
2117  }
2118  }
2119 
2120 fail:
2121  av_free(tracked_method);
2122  return ret;
2123 }
2124 
2126 {
2127  RTMPContext *rt = s->priv_data;
2128  const uint8_t *data_end = pkt->data + pkt->size;
2129  const uint8_t *ptr = pkt->data + RTMP_HEADER;
2130  uint8_t tmpstr[256];
2131  int i, t;
2132 
2133  for (i = 0; i < 2; i++) {
2134  t = ff_amf_tag_size(ptr, data_end);
2135  if (t < 0)
2136  return 1;
2137  ptr += t;
2138  }
2139 
2140  t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2141  if (!t && !strcmp(tmpstr, "error")) {
2142  t = ff_amf_get_field_value(ptr, data_end,
2143  "description", tmpstr, sizeof(tmpstr));
2144  if (t || !tmpstr[0])
2145  t = ff_amf_get_field_value(ptr, data_end, "code",
2146  tmpstr, sizeof(tmpstr));
2147  if (!t)
2148  av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2149  return -1;
2150  }
2151 
2152  t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2153  if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2154  if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2155  if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2156  if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2157  if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2158 
2159  return 0;
2160 }
2161 
2163 {
2164  RTMPContext *rt = s->priv_data;
2165  int ret = 0;
2166 
2167  //TODO: check for the messages sent for wrong state?
2168  if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2169  if ((ret = handle_invoke_error(s, pkt)) < 0)
2170  return ret;
2171  } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2172  if ((ret = handle_invoke_result(s, pkt)) < 0)
2173  return ret;
2174  } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2175  if ((ret = handle_invoke_status(s, pkt)) < 0)
2176  return ret;
2177  } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2178  if ((ret = gen_check_bw(s, rt)) < 0)
2179  return ret;
2180  } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2181  ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2182  ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2183  ff_amf_match_string(pkt->data, pkt->size, "play") ||
2184  ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2185  ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2186  if ((ret = send_invoke_response(s, pkt)) < 0)
2187  return ret;
2188  }
2189 
2190  return ret;
2191 }
2192 
2193 static int update_offset(RTMPContext *rt, int size)
2194 {
2195  int old_flv_size;
2196 
2197  // generate packet header and put data into buffer for FLV demuxer
2198  if (rt->flv_off < rt->flv_size) {
2199  // There is old unread data in the buffer, thus append at the end
2200  old_flv_size = rt->flv_size;
2201  rt->flv_size += size;
2202  } else {
2203  // All data has been read, write the new data at the start of the buffer
2204  old_flv_size = 0;
2205  rt->flv_size = size;
2206  rt->flv_off = 0;
2207  }
2208 
2209  return old_flv_size;
2210 }
2211 
2212 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2213 {
2214  int old_flv_size, ret;
2215  PutByteContext pbc;
2216  const uint8_t *data = pkt->data + skip;
2217  const int size = pkt->size - skip;
2218  uint32_t ts = pkt->timestamp;
2219 
2220  if (pkt->type == RTMP_PT_AUDIO) {
2221  rt->has_audio = 1;
2222  } else if (pkt->type == RTMP_PT_VIDEO) {
2223  rt->has_video = 1;
2224  }
2225 
2226  old_flv_size = update_offset(rt, size + 15);
2227 
2228  if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2229  rt->flv_size = rt->flv_off = 0;
2230  return ret;
2231  }
2232  bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2233  bytestream2_skip_p(&pbc, old_flv_size);
2234  bytestream2_put_byte(&pbc, pkt->type);
2235  bytestream2_put_be24(&pbc, size);
2236  bytestream2_put_be24(&pbc, ts);
2237  bytestream2_put_byte(&pbc, ts >> 24);
2238  bytestream2_put_be24(&pbc, 0);
2239  bytestream2_put_buffer(&pbc, data, size);
2240  bytestream2_put_be32(&pbc, 0);
2241 
2242  return 0;
2243 }
2244 
2246 {
2247  RTMPContext *rt = s->priv_data;
2248  uint8_t commandbuffer[64];
2249  char statusmsg[128];
2250  int stringlen, ret, skip = 0;
2251  GetByteContext gbc;
2252 
2253  bytestream2_init(&gbc, pkt->data, pkt->size);
2254  if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2255  &stringlen))
2256  return AVERROR_INVALIDDATA;
2257 
2258  if (!strcmp(commandbuffer, "onMetaData")) {
2259  // metadata properties should be stored in a mixed array
2260  if (bytestream2_get_byte(&gbc) == AMF_DATA_TYPE_MIXEDARRAY) {
2261  // We have found a metaData Array so flv can determine the streams
2262  // from this.
2263  rt->received_metadata = 1;
2264  // skip 32-bit max array index
2265  bytestream2_skip(&gbc, 4);
2266  while (bytestream2_get_bytes_left(&gbc) > 3) {
2267  if (ff_amf_get_string(&gbc, statusmsg, sizeof(statusmsg),
2268  &stringlen))
2269  return AVERROR_INVALIDDATA;
2270  // We do not care about the content of the property (yet).
2271  stringlen = ff_amf_tag_size(gbc.buffer, gbc.buffer_end);
2272  if (stringlen < 0)
2273  return AVERROR_INVALIDDATA;
2274  bytestream2_skip(&gbc, stringlen);
2275 
2276  // The presence of the following properties indicates that the
2277  // respective streams are present.
2278  if (!strcmp(statusmsg, "videocodecid")) {
2279  rt->has_video = 1;
2280  }
2281  if (!strcmp(statusmsg, "audiocodecid")) {
2282  rt->has_audio = 1;
2283  }
2284  }
2285  if (bytestream2_get_be24(&gbc) != AMF_END_OF_OBJECT)
2286  return AVERROR_INVALIDDATA;
2287  }
2288  }
2289 
2290  // Skip the @setDataFrame string and validate it is a notification
2291  if (!strcmp(commandbuffer, "@setDataFrame")) {
2292  skip = gbc.buffer - pkt->data;
2293  ret = ff_amf_read_string(&gbc, statusmsg,
2294  sizeof(statusmsg), &stringlen);
2295  if (ret < 0)
2296  return AVERROR_INVALIDDATA;
2297  }
2298 
2299  return append_flv_data(rt, pkt, skip);
2300 }
2301 
2302 /**
2303  * Parse received packet and possibly perform some action depending on
2304  * the packet contents.
2305  * @return 0 for no errors, negative values for serious errors which prevent
2306  * further communications, positive values for uncritical errors
2307  */
2309 {
2310  int ret;
2311 
2312 #ifdef DEBUG
2313  ff_rtmp_packet_dump(s, pkt);
2314 #endif
2315 
2316  switch (pkt->type) {
2317  case RTMP_PT_BYTES_READ:
2318  av_log(s, AV_LOG_TRACE, "received bytes read report\n");
2319  break;
2320  case RTMP_PT_CHUNK_SIZE:
2321  if ((ret = handle_chunk_size(s, pkt)) < 0)
2322  return ret;
2323  break;
2324  case RTMP_PT_PING:
2325  if ((ret = handle_ping(s, pkt)) < 0)
2326  return ret;
2327  break;
2328  case RTMP_PT_CLIENT_BW:
2329  if ((ret = handle_client_bw(s, pkt)) < 0)
2330  return ret;
2331  break;
2332  case RTMP_PT_SERVER_BW:
2333  if ((ret = handle_server_bw(s, pkt)) < 0)
2334  return ret;
2335  break;
2336  case RTMP_PT_INVOKE:
2337  if ((ret = handle_invoke(s, pkt)) < 0)
2338  return ret;
2339  break;
2340  case RTMP_PT_VIDEO:
2341  case RTMP_PT_AUDIO:
2342  case RTMP_PT_METADATA:
2343  case RTMP_PT_NOTIFY:
2344  /* Audio, Video and Metadata packets are parsed in get_packet() */
2345  break;
2346  default:
2347  av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2348  break;
2349  }
2350  return 0;
2351 }
2352 
2354 {
2355  int ret, old_flv_size, type;
2356  const uint8_t *next;
2357  uint8_t *p;
2358  uint32_t size;
2359  uint32_t ts, cts, pts = 0;
2360 
2361  old_flv_size = update_offset(rt, pkt->size);
2362 
2363  if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2364  rt->flv_size = rt->flv_off = 0;
2365  return ret;
2366  }
2367 
2368  next = pkt->data;
2369  p = rt->flv_data + old_flv_size;
2370 
2371  /* copy data while rewriting timestamps */
2372  ts = pkt->timestamp;
2373 
2374  while (next - pkt->data < pkt->size - RTMP_HEADER) {
2375  type = bytestream_get_byte(&next);
2376  size = bytestream_get_be24(&next);
2377  cts = bytestream_get_be24(&next);
2378  cts |= bytestream_get_byte(&next) << 24;
2379  if (!pts)
2380  pts = cts;
2381  ts += cts - pts;
2382  pts = cts;
2383  if (size + 3 + 4 > pkt->data + pkt->size - next)
2384  break;
2385  bytestream_put_byte(&p, type);
2386  bytestream_put_be24(&p, size);
2387  bytestream_put_be24(&p, ts);
2388  bytestream_put_byte(&p, ts >> 24);
2389  memcpy(p, next, size + 3 + 4);
2390  next += size + 3 + 4;
2391  p += size + 3 + 4;
2392  }
2393  if (p != rt->flv_data + rt->flv_size) {
2394  av_log(NULL, AV_LOG_WARNING, "Incomplete flv packets in "
2395  "RTMP_PT_METADATA packet\n");
2396  rt->flv_size = p - rt->flv_data;
2397  }
2398 
2399  return 0;
2400 }
2401 
2402 /**
2403  * Interact with the server by receiving and sending RTMP packets until
2404  * there is some significant data (media data or expected status notification).
2405  *
2406  * @param s reading context
2407  * @param for_header non-zero value tells function to work until it
2408  * gets notification from the server that playing has been started,
2409  * otherwise function will work until some media data is received (or
2410  * an error happens)
2411  * @return 0 for successful operation, negative value in case of error
2412  */
2413 static int get_packet(URLContext *s, int for_header)
2414 {
2415  RTMPContext *rt = s->priv_data;
2416  int ret;
2417 
2418  if (rt->state == STATE_STOPPED)
2419  return AVERROR_EOF;
2420 
2421  for (;;) {
2422  RTMPPacket rpkt = { 0 };
2423  if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2424  rt->in_chunk_size, &rt->prev_pkt[0],
2425  &rt->nb_prev_pkt[0])) <= 0) {
2426  if (ret == 0) {
2427  return AVERROR(EAGAIN);
2428  } else {
2429  return AVERROR(EIO);
2430  }
2431  }
2432 
2433  // Track timestamp for later use
2434  rt->last_timestamp = rpkt.timestamp;
2435 
2436  rt->bytes_read += ret;
2437  if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2438  av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2439  if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2440  return ret;
2441  rt->last_bytes_read = rt->bytes_read;
2442  }
2443 
2444  ret = rtmp_parse_result(s, rt, &rpkt);
2445 
2446  // At this point we must check if we are in the seek state and continue
2447  // with the next packet. handle_invoke will get us out of this state
2448  // when the right message is encountered
2449  if (rt->state == STATE_SEEKING) {
2450  ff_rtmp_packet_destroy(&rpkt);
2451  // We continue, let the natural flow of things happen:
2452  // AVERROR(EAGAIN) or handle_invoke gets us out of here
2453  continue;
2454  }
2455 
2456  if (ret < 0) {//serious error in current packet
2457  ff_rtmp_packet_destroy(&rpkt);
2458  return ret;
2459  }
2460  if (rt->do_reconnect && for_header) {
2461  ff_rtmp_packet_destroy(&rpkt);
2462  return 0;
2463  }
2464  if (rt->state == STATE_STOPPED) {
2465  ff_rtmp_packet_destroy(&rpkt);
2466  return AVERROR_EOF;
2467  }
2468  if (for_header && (rt->state == STATE_PLAYING ||
2469  rt->state == STATE_PUBLISHING ||
2470  rt->state == STATE_SENDING ||
2471  rt->state == STATE_RECEIVING)) {
2472  ff_rtmp_packet_destroy(&rpkt);
2473  return 0;
2474  }
2475  if (!rpkt.size || !rt->is_input) {
2476  ff_rtmp_packet_destroy(&rpkt);
2477  continue;
2478  }
2479  if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2480  ret = append_flv_data(rt, &rpkt, 0);
2481  ff_rtmp_packet_destroy(&rpkt);
2482  return ret;
2483  } else if (rpkt.type == RTMP_PT_NOTIFY) {
2484  ret = handle_notify(s, &rpkt);
2485  ff_rtmp_packet_destroy(&rpkt);
2486  return ret;
2487  } else if (rpkt.type == RTMP_PT_METADATA) {
2488  ret = handle_metadata(rt, &rpkt);
2489  ff_rtmp_packet_destroy(&rpkt);
2490  return 0;
2491  }
2492  ff_rtmp_packet_destroy(&rpkt);
2493  }
2494 }
2495 
2497 {
2498  RTMPContext *rt = h->priv_data;
2499  int ret = 0, i, j;
2500 
2501  if (!rt->is_input) {
2502  rt->flv_data = NULL;
2503  if (rt->out_pkt.size)
2505  if (rt->state > STATE_FCPUBLISH)
2506  ret = gen_fcunpublish_stream(h, rt);
2507  }
2508  if (rt->state > STATE_HANDSHAKED)
2509  ret = gen_delete_stream(h, rt);
2510  for (i = 0; i < 2; i++) {
2511  for (j = 0; j < rt->nb_prev_pkt[i]; j++)
2512  ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2513  av_freep(&rt->prev_pkt[i]);
2514  }
2515 
2517  av_freep(&rt->flv_data);
2518  ffurl_close(rt->stream);
2519  return ret;
2520 }
2521 
2522 /**
2523  * Insert a fake onMetadata packet into the FLV stream to notify the FLV
2524  * demuxer about the duration of the stream.
2525  *
2526  * This should only be done if there was no real onMetadata packet sent by the
2527  * server at the start of the stream and if we were able to retrieve a valid
2528  * duration via a getStreamLength call.
2529  *
2530  * @return 0 for successful operation, negative value in case of error
2531  */
2533 {
2534  // We need to insert the metdata packet directly after the FLV
2535  // header, i.e. we need to move all other already read data by the
2536  // size of our fake metadata packet.
2537 
2538  uint8_t* p;
2539  // Keep old flv_data pointer
2540  uint8_t* old_flv_data = rt->flv_data;
2541  // Allocate a new flv_data pointer with enough space for the additional package
2542  if (!(rt->flv_data = av_malloc(rt->flv_size + 55))) {
2543  rt->flv_data = old_flv_data;
2544  return AVERROR(ENOMEM);
2545  }
2546 
2547  // Copy FLV header
2548  memcpy(rt->flv_data, old_flv_data, 13);
2549  // Copy remaining packets
2550  memcpy(rt->flv_data + 13 + 55, old_flv_data + 13, rt->flv_size - 13);
2551  // Increase the size by the injected packet
2552  rt->flv_size += 55;
2553  // Delete the old FLV data
2554  av_freep(&old_flv_data);
2555 
2556  p = rt->flv_data + 13;
2557  bytestream_put_byte(&p, FLV_TAG_TYPE_META);
2558  bytestream_put_be24(&p, 40); // size of data part (sum of all parts below)
2559  bytestream_put_be24(&p, 0); // timestamp
2560  bytestream_put_be32(&p, 0); // reserved
2561 
2562  // first event name as a string
2563  bytestream_put_byte(&p, AMF_DATA_TYPE_STRING);
2564  // "onMetaData" as AMF string
2565  bytestream_put_be16(&p, 10);
2566  bytestream_put_buffer(&p, "onMetaData", 10);
2567 
2568  // mixed array (hash) with size and string/type/data tuples
2569  bytestream_put_byte(&p, AMF_DATA_TYPE_MIXEDARRAY);
2570  bytestream_put_be32(&p, 1); // metadata_count
2571 
2572  // "duration" as AMF string
2573  bytestream_put_be16(&p, 8);
2574  bytestream_put_buffer(&p, "duration", 8);
2575  bytestream_put_byte(&p, AMF_DATA_TYPE_NUMBER);
2576  bytestream_put_be64(&p, av_double2int(rt->duration));
2577 
2578  // Finalise object
2579  bytestream_put_be16(&p, 0); // Empty string
2580  bytestream_put_byte(&p, AMF_END_OF_OBJECT);
2581  bytestream_put_be32(&p, 40); // size of data part (sum of all parts below)
2582 
2583  return 0;
2584 }
2585 
2586 /**
2587  * Open RTMP connection and verify that the stream can be played.
2588  *
2589  * URL syntax: rtmp://server[:port][/app][/playpath]
2590  * where 'app' is first one or two directories in the path
2591  * (e.g. /ondemand/, /flash/live/, etc.)
2592  * and 'playpath' is a file name (the rest of the path,
2593  * may be prefixed with "mp4:")
2594  */
2595 static int rtmp_open(URLContext *s, const char *uri, int flags)
2596 {
2597  RTMPContext *rt = s->priv_data;
2598  char proto[8], hostname[256], path[1024], auth[100], *fname;
2599  char *old_app, *qmark, *n, fname_buffer[1024];
2600  uint8_t buf[2048];
2601  int port;
2602  AVDictionary *opts = NULL;
2603  int ret;
2604 
2605  if (rt->listen_timeout > 0)
2606  rt->listen = 1;
2607 
2608  rt->is_input = !(flags & AVIO_FLAG_WRITE);
2609 
2610  av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2611  hostname, sizeof(hostname), &port,
2612  path, sizeof(path), s->filename);
2613 
2614  n = strchr(path, ' ');
2615  if (n) {
2617  "Detected librtmp style URL parameters, these aren't supported "
2618  "by the libavformat internal RTMP handler currently enabled. "
2619  "See the documentation for the correct way to pass parameters.\n");
2620  *n = '\0'; // Trim not supported part
2621  }
2622 
2623  if (auth[0]) {
2624  char *ptr = strchr(auth, ':');
2625  if (ptr) {
2626  *ptr = '\0';
2627  av_strlcpy(rt->username, auth, sizeof(rt->username));
2628  av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2629  }
2630  }
2631 
2632  if (rt->listen && strcmp(proto, "rtmp")) {
2633  av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2634  proto);
2635  return AVERROR(EINVAL);
2636  }
2637  if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2638  if (!strcmp(proto, "rtmpts"))
2639  av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2640 
2641  /* open the http tunneling connection */
2642  ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2643  } else if (!strcmp(proto, "rtmps")) {
2644  /* open the tls connection */
2645  if (port < 0)
2646  port = RTMPS_DEFAULT_PORT;
2647  ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2648  } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2649  if (!strcmp(proto, "rtmpte"))
2650  av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2651 
2652  /* open the encrypted connection */
2653  ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2654  rt->encrypted = 1;
2655  } else {
2656  /* open the tcp connection */
2657  if (port < 0)
2658  port = RTMP_DEFAULT_PORT;
2659  if (rt->listen)
2660  ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2661  "?listen&listen_timeout=%d",
2662  rt->listen_timeout * 1000);
2663  else
2664  ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2665  }
2666 
2667 reconnect:
2668  if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2669  &s->interrupt_callback, &opts)) < 0) {
2670  av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2671  goto fail;
2672  }
2673 
2674  if (rt->swfverify) {
2675  if ((ret = rtmp_calc_swfhash(s)) < 0)
2676  goto fail;
2677  }
2678 
2679  rt->state = STATE_START;
2680  if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2681  goto fail;
2682  if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2683  goto fail;
2684 
2685  rt->out_chunk_size = 128;
2686  rt->in_chunk_size = 128; // Probably overwritten later
2687  rt->state = STATE_HANDSHAKED;
2688 
2689  // Keep the application name when it has been defined by the user.
2690  old_app = rt->app;
2691 
2692  rt->app = av_malloc(APP_MAX_LENGTH);
2693  if (!rt->app) {
2694  ret = AVERROR(ENOMEM);
2695  goto fail;
2696  }
2697 
2698  //extract "app" part from path
2699  qmark = strchr(path, '?');
2700  if (qmark && strstr(qmark, "slist=")) {
2701  char* amp;
2702  // After slist we have the playpath, before the params, the app
2703  av_strlcpy(rt->app, path + 1, FFMIN(qmark - path, APP_MAX_LENGTH));
2704  fname = strstr(path, "slist=") + 6;
2705  // Strip any further query parameters from fname
2706  amp = strchr(fname, '&');
2707  if (amp) {
2708  av_strlcpy(fname_buffer, fname, FFMIN(amp - fname + 1,
2709  sizeof(fname_buffer)));
2710  fname = fname_buffer;
2711  }
2712  } else if (!strncmp(path, "/ondemand/", 10)) {
2713  fname = path + 10;
2714  memcpy(rt->app, "ondemand", 9);
2715  } else {
2716  char *next = *path ? path + 1 : path;
2717  char *p = strchr(next, '/');
2718  if (!p) {
2719  if (old_app) {
2720  // If name of application has been defined by the user, assume that
2721  // playpath is provided in the URL
2722  fname = next;
2723  } else {
2724  fname = NULL;
2725  av_strlcpy(rt->app, next, APP_MAX_LENGTH);
2726  }
2727  } else {
2728  // make sure we do not mismatch a playpath for an application instance
2729  char *c = strchr(p + 1, ':');
2730  fname = strchr(p + 1, '/');
2731  if (!fname || (c && c < fname)) {
2732  fname = p + 1;
2733  av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2734  } else {
2735  fname++;
2736  av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2737  }
2738  }
2739  }
2740 
2741  if (old_app) {
2742  // The name of application has been defined by the user, override it.
2743  if (strlen(old_app) >= APP_MAX_LENGTH) {
2744  ret = AVERROR(EINVAL);
2745  goto fail;
2746  }
2747  av_free(rt->app);
2748  rt->app = old_app;
2749  }
2750 
2751  if (!rt->playpath) {
2753  if (!rt->playpath) {
2754  ret = AVERROR(ENOMEM);
2755  goto fail;
2756  }
2757 
2758  if (fname) {
2759  int len = strlen(fname);
2760  if (!strchr(fname, ':') && len >= 4 &&
2761  (!strcmp(fname + len - 4, ".f4v") ||
2762  !strcmp(fname + len - 4, ".mp4"))) {
2763  memcpy(rt->playpath, "mp4:", 5);
2764  } else {
2765  if (len >= 4 && !strcmp(fname + len - 4, ".flv"))
2766  fname[len - 4] = '\0';
2767  rt->playpath[0] = 0;
2768  }
2770  } else {
2771  rt->playpath[0] = '\0';
2772  }
2773  }
2774 
2775  if (!rt->tcurl) {
2777  if (!rt->tcurl) {
2778  ret = AVERROR(ENOMEM);
2779  goto fail;
2780  }
2781  ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2782  port, "/%s", rt->app);
2783  }
2784 
2785  if (!rt->flashver) {
2787  if (!rt->flashver) {
2788  ret = AVERROR(ENOMEM);
2789  goto fail;
2790  }
2791  if (rt->is_input) {
2792  snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2795  } else {
2797  "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2798  }
2799  }
2800 
2801  rt->client_report_size = 1048576;
2802  rt->bytes_read = 0;
2803  rt->has_audio = 0;
2804  rt->has_video = 0;
2805  rt->received_metadata = 0;
2806  rt->last_bytes_read = 0;
2807  rt->server_bw = 2500000;
2808  rt->duration = 0;
2809 
2810  av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2811  proto, path, rt->app, rt->playpath);
2812  if (!rt->listen) {
2813  if ((ret = gen_connect(s, rt)) < 0)
2814  goto fail;
2815  } else {
2816  if ((ret = read_connect(s, s->priv_data)) < 0)
2817  goto fail;
2818  }
2819 
2820  do {
2821  ret = get_packet(s, 1);
2822  } while (ret == AVERROR(EAGAIN));
2823  if (ret < 0)
2824  goto fail;
2825 
2826  if (rt->do_reconnect) {
2827  int i;
2828  ffurl_close(rt->stream);
2829  rt->stream = NULL;
2830  rt->do_reconnect = 0;
2831  rt->nb_invokes = 0;
2832  for (i = 0; i < 2; i++)
2833  memset(rt->prev_pkt[i], 0,
2834  sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
2836  goto reconnect;
2837  }
2838 
2839  if (rt->is_input) {
2840  // generate FLV header for demuxer
2841  rt->flv_size = 13;
2842  if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2843  goto fail;
2844  rt->flv_off = 0;
2845  memcpy(rt->flv_data, "FLV\1\0\0\0\0\011\0\0\0\0", rt->flv_size);
2846 
2847  // Read packets until we reach the first A/V packet or read metadata.
2848  // If there was a metadata package in front of the A/V packets, we can
2849  // build the FLV header from this. If we do not receive any metadata,
2850  // the FLV decoder will allocate the needed streams when their first
2851  // audio or video packet arrives.
2852  while (!rt->has_audio && !rt->has_video && !rt->received_metadata) {
2853  if ((ret = get_packet(s, 0)) < 0)
2854  goto fail;
2855  }
2856 
2857  // Either after we have read the metadata or (if there is none) the
2858  // first packet of an A/V stream, we have a better knowledge about the
2859  // streams, so set the FLV header accordingly.
2860  if (rt->has_audio) {
2862  }
2863  if (rt->has_video) {
2865  }
2866 
2867  // If we received the first packet of an A/V stream and no metadata but
2868  // the server returned a valid duration, create a fake metadata packet
2869  // to inform the FLV decoder about the duration.
2870  if (!rt->received_metadata && rt->duration > 0) {
2871  if ((ret = inject_fake_duration_metadata(rt)) < 0)
2872  goto fail;
2873  }
2874  } else {
2875  rt->flv_size = 0;
2876  rt->flv_data = NULL;
2877  rt->flv_off = 0;
2878  rt->skip_bytes = 13;
2879  }
2880 
2882  s->is_streamed = 1;
2883  return 0;
2884 
2885 fail:
2886  av_dict_free(&opts);
2887  rtmp_close(s);
2888  return ret;
2889 }
2890 
2891 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2892 {
2893  RTMPContext *rt = s->priv_data;
2894  int orig_size = size;
2895  int ret;
2896 
2897  while (size > 0) {
2898  int data_left = rt->flv_size - rt->flv_off;
2899 
2900  if (data_left >= size) {
2901  memcpy(buf, rt->flv_data + rt->flv_off, size);
2902  rt->flv_off += size;
2903  return orig_size;
2904  }
2905  if (data_left > 0) {
2906  memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2907  buf += data_left;
2908  size -= data_left;
2909  rt->flv_off = rt->flv_size;
2910  return data_left;
2911  }
2912  if ((ret = get_packet(s, 0)) < 0)
2913  return ret;
2914  }
2915  return orig_size;
2916 }
2917 
2918 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2919  int flags)
2920 {
2921  RTMPContext *rt = s->priv_data;
2922  int ret;
2923  av_log(s, AV_LOG_DEBUG,
2924  "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2925  stream_index, timestamp, flags);
2926  if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2927  av_log(s, AV_LOG_ERROR,
2928  "Unable to send seek command on stream index %d at timestamp "
2929  "%"PRId64" with flags %08x\n",
2930  stream_index, timestamp, flags);
2931  return ret;
2932  }
2933  rt->flv_off = rt->flv_size;
2934  rt->state = STATE_SEEKING;
2935  return timestamp;
2936 }
2937 
2938 static int rtmp_pause(URLContext *s, int pause)
2939 {
2940  RTMPContext *rt = s->priv_data;
2941  int ret;
2942  av_log(s, AV_LOG_DEBUG, "Pause at timestamp %d\n",
2943  rt->last_timestamp);
2944  if ((ret = gen_pause(s, rt, pause, rt->last_timestamp)) < 0) {
2945  av_log(s, AV_LOG_ERROR, "Unable to send pause command at timestamp %d\n",
2946  rt->last_timestamp);
2947  return ret;
2948  }
2949  return 0;
2950 }
2951 
2952 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2953 {
2954  RTMPContext *rt = s->priv_data;
2955  int size_temp = size;
2956  int pktsize, pkttype, copy;
2957  uint32_t ts;
2958  const uint8_t *buf_temp = buf;
2959  uint8_t c;
2960  int ret;
2961 
2962  do {
2963  if (rt->skip_bytes) {
2964  int skip = FFMIN(rt->skip_bytes, size_temp);
2965  buf_temp += skip;
2966  size_temp -= skip;
2967  rt->skip_bytes -= skip;
2968  continue;
2969  }
2970 
2971  if (rt->flv_header_bytes < RTMP_HEADER) {
2972  const uint8_t *header = rt->flv_header;
2973  int channel = RTMP_AUDIO_CHANNEL;
2974 
2975  copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
2976  bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2977  rt->flv_header_bytes += copy;
2978  size_temp -= copy;
2979  if (rt->flv_header_bytes < RTMP_HEADER)
2980  break;
2981 
2982  pkttype = bytestream_get_byte(&header);
2983  pktsize = bytestream_get_be24(&header);
2984  ts = bytestream_get_be24(&header);
2985  ts |= bytestream_get_byte(&header) << 24;
2986  bytestream_get_be24(&header);
2987  rt->flv_size = pktsize;
2988 
2989  if (pkttype == RTMP_PT_VIDEO)
2990  channel = RTMP_VIDEO_CHANNEL;
2991 
2992  if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2993  pkttype == RTMP_PT_NOTIFY) {
2994  if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
2995  &rt->nb_prev_pkt[1],
2996  channel)) < 0)
2997  return ret;
2998  // Force sending a full 12 bytes header by clearing the
2999  // channel id, to make it not match a potential earlier
3000  // packet in the same channel.
3001  rt->prev_pkt[1][channel].channel_id = 0;
3002  }
3003 
3004  //this can be a big packet, it's better to send it right here
3005  if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
3006  pkttype, ts, pktsize)) < 0)
3007  return ret;
3008 
3009  rt->out_pkt.extra = rt->stream_id;
3010  rt->flv_data = rt->out_pkt.data;
3011  }
3012 
3013  copy = FFMIN(rt->flv_size - rt->flv_off, size_temp);
3014  bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, copy);
3015  rt->flv_off += copy;
3016  size_temp -= copy;
3017 
3018  if (rt->flv_off == rt->flv_size) {
3019  rt->skip_bytes = 4;
3020 
3021  if (rt->out_pkt.type == RTMP_PT_NOTIFY) {
3022  // For onMetaData and |RtmpSampleAccess packets, we want
3023  // @setDataFrame prepended to the packet before it gets sent.
3024  // However, not all RTMP_PT_NOTIFY packets (e.g., onTextData
3025  // and onCuePoint).
3026  uint8_t commandbuffer[64];
3027  int stringlen = 0;
3028  GetByteContext gbc;
3029 
3030  bytestream2_init(&gbc, rt->flv_data, rt->flv_size);
3031  if (!ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
3032  &stringlen)) {
3033  if (!strcmp(commandbuffer, "onMetaData") ||
3034  !strcmp(commandbuffer, "|RtmpSampleAccess")) {
3035  uint8_t *ptr;
3036  if ((ret = av_reallocp(&rt->out_pkt.data, rt->out_pkt.size + 16)) < 0) {
3037  rt->flv_size = rt->flv_off = rt->flv_header_bytes = 0;
3038  return ret;
3039  }
3040  memmove(rt->out_pkt.data + 16, rt->out_pkt.data, rt->out_pkt.size);
3041  rt->out_pkt.size += 16;
3042  ptr = rt->out_pkt.data;
3043  ff_amf_write_string(&ptr, "@setDataFrame");
3044  }
3045  }
3046  }
3047 
3048  if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
3049  return ret;
3050  rt->flv_size = 0;
3051  rt->flv_off = 0;
3052  rt->flv_header_bytes = 0;
3053  rt->flv_nb_packets++;
3054  }
3055  } while (buf_temp - buf < size);
3056 
3057  if (rt->flv_nb_packets < rt->flush_interval)
3058  return size;
3059  rt->flv_nb_packets = 0;
3060 
3061  /* set stream into nonblocking mode */
3063 
3064  /* try to read one byte from the stream */
3065  ret = ffurl_read(rt->stream, &c, 1);
3066 
3067  /* switch the stream back into blocking mode */
3068  rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
3069 
3070  if (ret == AVERROR(EAGAIN)) {
3071  /* no incoming data to handle */
3072  return size;
3073  } else if (ret < 0) {
3074  return ret;
3075  } else if (ret == 1) {
3076  RTMPPacket rpkt = { 0 };
3077 
3078  if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
3079  rt->in_chunk_size,
3080  &rt->prev_pkt[0],
3081  &rt->nb_prev_pkt[0], c)) <= 0)
3082  return ret;
3083 
3084  if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
3085  return ret;
3086 
3087  ff_rtmp_packet_destroy(&rpkt);
3088  }
3089 
3090  return size;
3091 }
3092 
3093 #define OFFSET(x) offsetof(RTMPContext, x)
3094 #define DEC AV_OPT_FLAG_DECODING_PARAM
3095 #define ENC AV_OPT_FLAG_ENCODING_PARAM
3096 
3097 static const AVOption rtmp_options[] = {
3098  {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3099  {"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},
3100  {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3101  {"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},
3102  {"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},
3103  {"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"},
3104  {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
3105  {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
3106  {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
3107  {"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},
3108  {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3109  {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
3110  {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
3111  {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
3112  {"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},
3113  {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
3114  {"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},
3115  {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
3116  {"listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
3117  {"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" },
3118  { NULL },
3119 };
3120 
3121 #define RTMP_PROTOCOL(flavor) \
3122 static const AVClass flavor##_class = { \
3123  .class_name = #flavor, \
3124  .item_name = av_default_item_name, \
3125  .option = rtmp_options, \
3126  .version = LIBAVUTIL_VERSION_INT, \
3127 }; \
3128  \
3129 URLProtocol ff_##flavor##_protocol = { \
3130  .name = #flavor, \
3131  .url_open = rtmp_open, \
3132  .url_read = rtmp_read, \
3133  .url_read_seek = rtmp_seek, \
3134  .url_read_pause = rtmp_pause, \
3135  .url_write = rtmp_write, \
3136  .url_close = rtmp_close, \
3137  .priv_data_size = sizeof(RTMPContext), \
3138  .flags = URL_PROTOCOL_FLAG_NETWORK, \
3139  .priv_data_class= &flavor##_class, \
3140 };
3141 
3142 
3143 RTMP_PROTOCOL(rtmp)
3144 RTMP_PROTOCOL(rtmpe)
3145 RTMP_PROTOCOL(rtmps)
3146 RTMP_PROTOCOL(rtmpt)
3147 RTMP_PROTOCOL(rtmpte)
3148 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:920
Definition: lfg.h:25
void av_sha_final(AVSHA *ctx, uint8_t *digest)
Finish hashing and output digest value.
Definition: sha.c:341
#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.
Definition: utils.c:3886
static int gen_swf_verification(URLContext *s, RTMPContext *rt)
Generate SWF verification message and send it to the server.
Definition: rtmpproto.c:859
#define NULL
Definition: coverity.c:32
int ff_amf_match_string(const uint8_t *data, int size, const char *str)
Match AMF string with a NULL-terminated string.
Definition: rtmppkt.c:635
int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket **prev_pkt, int *nb_prev_pkt, uint8_t hdr)
Read internal RTMP packet sent by the server.
Definition: rtmppkt.c:290
static int rtmp_read(URLContext *s, uint8_t *buf, int size)
Definition: rtmpproto.c:2891
video packet
Definition: rtmppkt.h:54
const char * s
Definition: avisynth_c.h:631
int live
0: recorded, -1: live, -2: both
Definition: rtmpproto.c:86
#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:131
static int gen_pause(URLContext *s, RTMPContext *rt, int pause, uint32_t timestamp)
Generate a pause packet that either pauses or unpauses the current stream.
Definition: rtmpproto.c:779
uint8_t flv_header[RTMP_HEADER]
partial incoming flv packet header
Definition: rtmpproto.c:104
void av_sha_update(AVSHA *ctx, const uint8_t *data, unsigned int len)
Update hash value.
Definition: sha.c:314
AVOption.
Definition: opt.h:255
hash context
Definition: sha.c:34
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
Definition: rtmpproto.c:2952
static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1803
enum AVCodecID id
Definition: mxfenc.c:99
client bandwidth
Definition: rtmppkt.h:52
static int handle_invoke(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:2162
int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket **prev_pkt, int *nb_prev_pkt)
Read RTMP packet sent by the server.
Definition: rtmppkt.c:159
#define RTMP_CLIENT_VER2
Definition: rtmp.h:41
av_cold int av_sha_init(AVSHA *ctx, int bits)
Initialize SHA-1 or SHA-2 hashing.
Definition: sha.c:273
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
static int gen_check_bw(URLContext *s, RTMPContext *rt)
Generate check bandwidth message and send it to the server.
Definition: rtmpproto.c:899
static const uint8_t rtmp_server_key[]
Key used for RTMP server digest signing.
Definition: rtmpproto.c:148
else temp
Definition: vf_mcdeint.c:257
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:347
#define RTMPS_DEFAULT_PORT
Definition: rtmp.h:28
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:46
static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt, const char *subscribe)
Definition: rtmpproto.c:936
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:105
AVIOInterruptCB interrupt_callback
Definition: url.h:48
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
Definition: bytestream.h:141
#define AVIO_FLAG_READ
read-only
Definition: avio.h:460
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:461
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:428
static int gen_create_stream(URLContext *s, RTMPContext *rt)
Generate 'createStream' call and send it to the server.
Definition: rtmpproto.c:634
#define TCURL_MAX_LENGTH
Definition: rtmpproto.c:53
static av_always_inline uint64_t av_double2int(double f)
Reinterpret a double as a 64-bit integer.
Definition: intfloat.h:70
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:131
int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags)
Definition: opt.c:506
int flags
Definition: url.h:44
URLContext * stream
TCP stream used in interactions with RTMP server.
Definition: rtmpproto.c:79
static AVPacket pkt
int in_chunk_size
size of the chunks incoming RTMP packets are divided into
Definition: rtmpproto.c:82
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:85
double duration
Duration of the stream in seconds as returned by the server (only valid if non-zero) ...
Definition: rtmpproto.c:127
int skip_bytes
number of bytes to skip from the input FLV stream in the next write call
Definition: rtmpproto.c:100
#define DEC
Definition: rtmpproto.c:3094
uint32_t last_bytes_read
number of bytes read last reported to server
Definition: rtmpproto.c:98
static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
rtmp handshake server side
Definition: rtmpproto.c:1434
void av_md5_update(AVMD5 *ctx, const uint8_t *src, int len)
Update hash value.
Definition: md5.c:148
RTMPPacketType type
packet payload type
Definition: rtmppkt.h:79
channel for a/v invokes
Definition: rtmppkt.h:41
ping
Definition: rtmppkt.h:50
int flv_nb_packets
number of flv packets published
Definition: rtmpproto.c:94
char password[50]
Definition: rtmpproto.c:129
static const char signature[]
Definition: ipmovie.c:529
struct AVMD5 * av_md5_alloc(void)
Allocate an AVMD5 context.
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:956
if()
Definition: avfilter.c:975
uint8_t
static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
Definition: rtmpproto.c:2212
#define av_malloc(s)
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:89
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:204
static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
Generate 'FCUnpublish' call and send it to the server.
Definition: rtmpproto.c:610
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:85
#define RTMP_PKTDATA_DEFAULT_SIZE
Definition: rtmpproto.c:55
TrackedMethod * tracked_methods
tracked methods buffer
Definition: rtmpproto.c:121
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:254
int av_reallocp(void *ptr, size_t size)
Allocate or reallocate a block of memory.
Definition: mem.c:185
const uint8_t * buffer
Definition: bytestream.h:34
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:609
#define RTMP_HEADER
Definition: rtmpproto.c:56
int nb_invokes
keeps track of invoke messages
Definition: rtmpproto.c:106
int out_chunk_size
size of the chunks outgoing RTMP packets are divided into
Definition: rtmpproto.c:83
#define AVERROR_EOF
End of file.
Definition: error.h:55
int flv_size
current buffer size
Definition: rtmpproto.c:92
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
int listen_timeout
listen timeout to wait for new connections
Definition: rtmpproto.c:125
int flush_interval
number of packets flushed in the same request (RTMPT only)
Definition: rtmpproto.c:119
#define APP_MAX_LENGTH
Definition: rtmpproto.c:51
static void copy(LZOContext *c, int cnt)
Copies bytes from input to output buffer with checking.
Definition: lzo.c:85
ptrdiff_t size
Definition: opengl_enc.c:101
char * swfverify
URL to player swf file, compute hash/size automatically.
Definition: rtmpproto.c:113
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:1214
int encrypted
use an encrypted connection (RTMPE only)
Definition: rtmpproto.c:120
static const uint8_t header[24]
Definition: sdr2.c:67
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:998
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:88
received a play command (for output)
Definition: rtmpproto.c:67
#define av_log(a,...)
static void del_tracked_method(RTMPContext *rt, int index)
Definition: rtmpproto.c:183
static int rtmp_validate_digest(uint8_t *buf, int off)
Verify that the received server response has the expected digest value.
Definition: rtmpproto.c:1043
int size
packet payload size
Definition: rtmppkt.h:84
static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
Definition: rtmpproto.c:753
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:1614
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:1018
number of bytes read
Definition: rtmppkt.h:49
char * name
Definition: rtmpproto.c:72
static int write_status(URLContext *s, RTMPPacket *pkt, const char *status, const char *filename)
Definition: rtmpproto.c:1868
static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1568
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
char * pageurl
url of the web page
Definition: rtmpproto.c:115
char auth_params[500]
Definition: rtmpproto.c:130
client has started the seek operation. Back on STATE_PLAYING when the time comes
Definition: rtmpproto.c:64
static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
Definition: rtmpproto.c:226
static int inject_fake_duration_metadata(RTMPContext *rt)
Insert a fake onMetadata packet into the FLV stream to notify the FLV demuxer about the duration of t...
Definition: rtmpproto.c:2532
#define AVERROR(e)
Definition: error.h:43
char * flashver
version of the flash plugin
Definition: rtmpproto.c:108
static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:2125
ClientState
RTMP protocol handler state.
Definition: rtmpproto.c:59
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:162
char * swfurl
url of the swf player
Definition: rtmpproto.c:112
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
#define PLAYER_KEY_OPEN_PART_LEN
length of partial key used for first client digest signing
Definition: rtmpproto.c:135
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:199
audio packet
Definition: rtmppkt.h:53
static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
Generate 'FCPublish' call and send it to the server.
Definition: rtmpproto.c:586
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:152
static int gen_delete_stream(URLContext *s, RTMPContext *rt)
Generate 'deleteStream' call and send it to the server.
Definition: rtmpproto.c:659
char * playpath
stream identifier to play (with possible "mp4:" prefix)
Definition: rtmpproto.c:85
int ff_amf_get_string(GetByteContext *bc, uint8_t *str, int strsize, int *length)
Get AMF string value.
Definition: rtmppkt.c:105
client has not done anything yet
Definition: rtmpproto.c:60
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
char * av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
Encode data to base64 and null-terminate.
Definition: base64.c:138
static void free_tracked_methods(RTMPContext *rt)
Definition: rtmpproto.c:215
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:83
int tracked_methods_size
size of the tracked methods buffer
Definition: rtmpproto.c:123
static int rtmp_pause(URLContext *s, int pause)
Definition: rtmpproto.c:2938
#define RTMP_PROTOCOL(flavor)
Definition: rtmpproto.c:3121
#define OFFSET(x)
Definition: rtmpproto.c:3093
client has performed handshake
Definition: rtmpproto.c:61
static int gen_play(URLContext *s, RTMPContext *rt)
Generate 'play' call and send it to the server, then ping the server to start actual playing...
Definition: rtmpproto.c:729
const uint8_t * buffer_end
Definition: bytestream.h:34
static av_always_inline void bytestream2_skip_p(PutByteContext *p, unsigned int size)
Definition: bytestream.h:174
#define PLAYPATH_MAX_LENGTH
Definition: rtmpproto.c:52
int swfhash_len
length of the SHA256 hash
Definition: rtmpproto.c:110
#define LIBAVFORMAT_IDENT
Definition: version.h:44
server bandwidth
Definition: rtmppkt.h:51
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:2308
#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:66
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:420
int auth_tried
Definition: rtmpproto.c:132
ret
Definition: avfilter.c:974
static int gen_publish(URLContext *s, RTMPContext *rt)
Generate 'publish' call and send it to the server.
Definition: rtmpproto.c:806
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:109
client has started receiving multimedia data from server
Definition: rtmpproto.c:63
int client_buffer_time
client buffer time in ms
Definition: rtmpproto.c:118
client FCPublishing stream (for output)
Definition: rtmpproto.c:62
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:471
static int rtmp_close(URLContext *h)
Definition: rtmpproto.c:2496
int nb_streamid
The next stream id to return on createStream calls.
Definition: rtmpproto.c:126
#define ENC
Definition: rtmpproto.c:3095
#define RTMP_CLIENT_PLATFORM
emulated Flash client version - 9.0.124.2 on Linux
Definition: rtmp.h:39
int has_video
presence of video data
Definition: rtmpproto.c:102
static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
Generate ping reply and send it to the server.
Definition: rtmpproto.c:833
static int add_tracked_method(RTMPContext *rt, const char *name, int id)
Definition: rtmpproto.c:160
int is_input
input/output flag
Definition: rtmpproto.c:84
static const uint8_t rtmp_player_key[]
Client key used for digest signing.
Definition: rtmpproto.c:137
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:1414
int n
Definition: avisynth_c.h:547
static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp, int flags)
Definition: rtmpproto.c:2918
int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, int chunk_size, RTMPPacket **prev_pkt_ptr, int *nb_prev_pkt)
Send RTMP packet to the server.
Definition: rtmppkt.c:305
static int gen_get_stream_length(URLContext *s, RTMPContext *rt)
Generate 'getStreamLength' call and send it to the server.
Definition: rtmpproto.c:685
static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, uint8_t *dst, unsigned int size)
Definition: bytestream.h:357
static int gen_buffer_time(URLContext *s, RTMPContext *rt)
Generate client buffer time and send it to the server.
Definition: rtmpproto.c:707
static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, const uint8_t *src, unsigned int size)
Definition: bytestream.h:280
the broadcast has been stopped
Definition: rtmpproto.c:68
char * swfhash
SHA256 hash of the decompressed SWF file (32 bytes)
Definition: rtmpproto.c:109
char swfverification[42]
hash of the SWF verification
Definition: rtmpproto.c:114
int nb_tracked_methods
number of tracked methods
Definition: rtmpproto.c:122
offset must point to a pointer immediately followed by an int for the length
Definition: opt.h:229
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
Definition: url.c:36
static struct AVHashContext * hash
Definition: ffprobe.c:216
static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
Definition: rtmpproto.c:1653
chunk size change
Definition: rtmppkt.h:48
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
char username[50]
Definition: rtmpproto.c:128
FLV common header.
int flv_off
number of bytes read from current buffer
Definition: rtmpproto.c:93
AVS_Value src
Definition: avisynth_c.h:482
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:265
static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1508
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:479
uint32_t bytes_read
number of bytes read from server
Definition: rtmpproto.c:97
static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Definition: vf_drawtext.c:765
struct AVSHA * av_sha_alloc(void)
Allocate an AVSHA context.
Definition: sha.c:45
void av_md5_init(AVMD5 *ctx)
Initialize MD5 hashing.
Definition: md5.c:138
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:38
uint32_t last_timestamp
last timestamp received in a packet
Definition: rtmpproto.c:99
void * buf
Definition: avisynth_c.h:553
Definition: url.h:39
char * subscribe
name of live stream to subscribe
Definition: rtmpproto.c:116
void ff_rtmpe_encrypt_sig(URLContext *h, uint8_t *sig, const uint8_t *digest, int type)
Encrypt the signature.
Definition: rtmpcrypt.c:207
GLint GLenum type
Definition: opengl_enc.c:105
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition: avio.h:462
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:69
channel for sending server control messages
Definition: rtmppkt.h:38
static int gen_connect(URLContext *s, RTMPContext *rt)
Generate 'connect' call and send it to the server.
Definition: rtmpproto.c:317
static int gen_release_stream(URLContext *s, RTMPContext *rt)
Generate 'releaseStream' call and send it to the server.
Definition: rtmpproto.c:562
#define HMAC_OPAD_VAL
Definition: rtmp.h:33
Describe the class of an AVClass context structure.
Definition: log.h:67
static int write_begin(URLContext *s)
Definition: rtmpproto.c:1842
#define AV_WB32(p, v)
Definition: intreadwrite.h:419
static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset, char **tracked_method)
Definition: rtmpproto.c:190
int index
Definition: gxfenc.c:89
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:402
void * priv_data
Definition: url.h:42
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:2245
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
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
RTMPPacket out_pkt
rtmp packet, created from flv a/v or metadata (for output)
Definition: rtmpproto.c:95
#define snprintf
Definition: snprintf.h:34
char * tcurl
url of the target stream
Definition: rtmpproto.c:107
static int handle_connect_error(URLContext *s, const char *desc)
Definition: rtmpproto.c:1712
void av_md5_final(AVMD5 *ctx, uint8_t *dst)
Finish hashing and output digest value.
Definition: md5.c:183
channel for audio data
Definition: rtmppkt.h:39
int listen
listen mode flag
Definition: rtmpproto.c:124
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:93
some notification
Definition: rtmppkt.h:58
#define AMF_END_OF_OBJECT
Definition: flv.h:47
static int rtmp_receive_hs_packet(RTMPContext *rt, uint32_t *first_int, uint32_t *second_int, char *arraydata, int size)
Definition: rtmpproto.c:1393
#define HMAC_IPAD_VAL
Definition: rtmp.h:32
static int64_t pts
Global timestamp for the audio frames.
static int flags
Definition: cpu.c:47
int ffurl_close(URLContext *h)
Definition: avio.c:392
#define SERVER_KEY_OPEN_PART_LEN
length of partial key used for first server digest signing
Definition: rtmpproto.c:146
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:880
uint8_t level
Definition: svq3.c:150
static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
Definition: rtmpproto.c:2353
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:54
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:2595
int stream_id
ID assigned by the server for the stream.
Definition: rtmpproto.c:90
int has_audio
presence of audio data
Definition: rtmpproto.c:101
RTMPPacket * prev_pkt[2]
packet history used when reading and sending packets ([0] for reading, [1] for writing) ...
Definition: rtmpproto.c:80
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:360
char * app
name of application
Definition: rtmpproto.c:87
void * av_realloc(void *ptr, size_t size)
Allocate or reallocate a block of memory.
Definition: mem.c:143
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:272
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:340
static int rtmp_calc_swfhash(URLContext *s)
Definition: rtmpproto.c:1129
char * filename
specified URL
Definition: url.h:43
int ff_rtmp_check_alloc_array(RTMPPacket **prev_pkt, int *nb_prev_pkt, int channel)
Enlarge the prev_pkt array to fit the given channel.
Definition: rtmppkt.c:138
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
Definition: avio.h:339
#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:123
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition: bytestream.h:366
static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1914
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:3097
#define av_free(p)
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:2413
static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:2053
int len
uint8_t * flv_data
buffer with data for demuxer
Definition: rtmpproto.c:91
static int read_connect(URLContext *s, RTMPContext *rt)
Definition: rtmpproto.c:402
int received_metadata
Indicates if we have received metadata about the streams.
Definition: rtmpproto.c:103
static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1592
#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:131
#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:45
protocol handler context
Definition: rtmpproto.c:77
#define av_freep(p)
int swfsize
size of the decompressed SWF file
Definition: rtmpproto.c:111
int nb_prev_pkt[2]
number of elements in prev_pkt
Definition: rtmpproto.c:81
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
static int update_offset(RTMPContext *rt, int size)
Definition: rtmpproto.c:2193
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:109
static int handle_ping(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1541
char * ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase)
Definition: utils.c:3957
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:333
uint32_t client_report_size
number of bytes after which client should report to server
Definition: rtmpproto.c:96
int server_bw
server bandwidth
Definition: rtmpproto.c:117
FLV metadata.
Definition: rtmppkt.h:61
GLuint buffer
Definition: opengl_enc.c:102
static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt, uint8_t *buf)
Definition: rtmpproto.c:1061
const char * name
Definition: opengl_enc.c:103
static int read_number_result(RTMPPacket *pkt, double *number)
Read the AMF_NUMBER response ("_result") to a function call (e.g.
Definition: rtmpproto.c:2023