FFmpeg
rtmppkt.c
Go to the documentation of this file.
1 /*
2  * RTMP input format
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 #include "libavcodec/bytestream.h"
23 #include "libavutil/avstring.h"
24 #include "libavutil/intfloat.h"
25 #include "avformat.h"
26 
27 #include "rtmppkt.h"
28 #include "flv.h"
29 #include "url.h"
30 
31 void ff_amf_write_bool(uint8_t **dst, int val)
32 {
33  bytestream_put_byte(dst, AMF_DATA_TYPE_BOOL);
34  bytestream_put_byte(dst, val);
35 }
36 
37 void ff_amf_write_number(uint8_t **dst, double val)
38 {
39  bytestream_put_byte(dst, AMF_DATA_TYPE_NUMBER);
40  bytestream_put_be64(dst, av_double2int(val));
41 }
42 
43 void ff_amf_write_array_start(uint8_t **dst, uint32_t length)
44 {
45  bytestream_put_byte(dst, AMF_DATA_TYPE_ARRAY);
46  bytestream_put_be32(dst, length);
47 }
48 
49 void ff_amf_write_string(uint8_t **dst, const char *str)
50 {
51  bytestream_put_byte(dst, AMF_DATA_TYPE_STRING);
52  bytestream_put_be16(dst, strlen(str));
53  bytestream_put_buffer(dst, str, strlen(str));
54 }
55 
56 void ff_amf_write_string2(uint8_t **dst, const char *str1, const char *str2)
57 {
58  int len1 = 0, len2 = 0;
59  if (str1)
60  len1 = strlen(str1);
61  if (str2)
62  len2 = strlen(str2);
63  bytestream_put_byte(dst, AMF_DATA_TYPE_STRING);
64  bytestream_put_be16(dst, len1 + len2);
65  bytestream_put_buffer(dst, str1, len1);
66  bytestream_put_buffer(dst, str2, len2);
67 }
68 
69 void ff_amf_write_null(uint8_t **dst)
70 {
71  bytestream_put_byte(dst, AMF_DATA_TYPE_NULL);
72 }
73 
74 void ff_amf_write_object_start(uint8_t **dst)
75 {
76  bytestream_put_byte(dst, AMF_DATA_TYPE_OBJECT);
77 }
78 
79 void ff_amf_write_field_name(uint8_t **dst, const char *str)
80 {
81  bytestream_put_be16(dst, strlen(str));
82  bytestream_put_buffer(dst, str, strlen(str));
83 }
84 
85 void ff_amf_write_object_end(uint8_t **dst)
86 {
87  /* first two bytes are field name length = 0,
88  * AMF object should end with it and end marker
89  */
90  bytestream_put_be24(dst, AMF_DATA_TYPE_OBJECT_END);
91 }
92 
94 {
95  uint64_t read;
96  if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_NUMBER)
97  return AVERROR_INVALIDDATA;
98  read = bytestream2_get_be64(bc);
100  return 0;
101 }
102 
103 int ff_amf_get_string(GetByteContext *bc, uint8_t *str,
104  int strsize, int *length)
105 {
106  int stringlen = 0;
107  int readsize;
108  stringlen = bytestream2_get_be16(bc);
109  if (stringlen + 1 > strsize)
110  return AVERROR(EINVAL);
111  readsize = bytestream2_get_buffer(bc, str, stringlen);
112  if (readsize != stringlen) {
114  "Unable to read as many bytes as AMF string signaled\n");
115  }
116  str[readsize] = '\0';
117  *length = FFMIN(stringlen, readsize);
118  return 0;
119 }
120 
121 int ff_amf_read_string(GetByteContext *bc, uint8_t *str,
122  int strsize, int *length)
123 {
124  if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_STRING)
125  return AVERROR_INVALIDDATA;
126  return ff_amf_get_string(bc, str, strsize, length);
127 }
128 
130 {
131  if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_NULL)
132  return AVERROR_INVALIDDATA;
133  return 0;
134 }
135 
136 int ff_rtmp_check_alloc_array(RTMPPacket **prev_pkt, int *nb_prev_pkt,
137  int channel)
138 {
139  int nb_alloc;
140  RTMPPacket *ptr;
141  if (channel < *nb_prev_pkt)
142  return 0;
143 
144  nb_alloc = channel + 16;
145  // This can't use the av_reallocp family of functions, since we
146  // would need to free each element in the array before the array
147  // itself is freed.
148  ptr = av_realloc_array(*prev_pkt, nb_alloc, sizeof(**prev_pkt));
149  if (!ptr)
150  return AVERROR(ENOMEM);
151  memset(ptr + *nb_prev_pkt, 0, (nb_alloc - *nb_prev_pkt) * sizeof(*ptr));
152  *prev_pkt = ptr;
153  *nb_prev_pkt = nb_alloc;
154  return 0;
155 }
156 
158  int chunk_size, RTMPPacket **prev_pkt, int *nb_prev_pkt)
159 {
160  uint8_t hdr;
161 
162  if (ffurl_read(h, &hdr, 1) != 1)
163  return AVERROR(EIO);
164 
165  return ff_rtmp_packet_read_internal(h, p, chunk_size, prev_pkt,
166  nb_prev_pkt, hdr);
167 }
168 
170  int chunk_size, RTMPPacket **prev_pkt_ptr,
171  int *nb_prev_pkt, uint8_t hdr)
172 {
173 
174  uint8_t buf[16];
175  int channel_id, timestamp, size;
176  uint32_t ts_field; // non-extended timestamp or delta field
177  uint32_t extra = 0;
178  enum RTMPPacketType type;
179  int written = 0;
180  int ret, toread;
181  RTMPPacket *prev_pkt;
182 
183  written++;
184  channel_id = hdr & 0x3F;
185 
186  if (channel_id < 2) { //special case for channel number >= 64
187  buf[1] = 0;
188  if (ffurl_read_complete(h, buf, channel_id + 1) != channel_id + 1)
189  return AVERROR(EIO);
190  written += channel_id + 1;
191  channel_id = AV_RL16(buf) + 64;
192  }
193  if ((ret = ff_rtmp_check_alloc_array(prev_pkt_ptr, nb_prev_pkt,
194  channel_id)) < 0)
195  return ret;
196  prev_pkt = *prev_pkt_ptr;
197  size = prev_pkt[channel_id].size;
198  type = prev_pkt[channel_id].type;
199  extra = prev_pkt[channel_id].extra;
200 
201  hdr >>= 6; // header size indicator
202  if (hdr == RTMP_PS_ONEBYTE) {
203  ts_field = prev_pkt[channel_id].ts_field;
204  } else {
205  if (ffurl_read_complete(h, buf, 3) != 3)
206  return AVERROR(EIO);
207  written += 3;
208  ts_field = AV_RB24(buf);
209  if (hdr != RTMP_PS_FOURBYTES) {
210  if (ffurl_read_complete(h, buf, 3) != 3)
211  return AVERROR(EIO);
212  written += 3;
213  size = AV_RB24(buf);
214  if (ffurl_read_complete(h, buf, 1) != 1)
215  return AVERROR(EIO);
216  written++;
217  type = buf[0];
218  if (hdr == RTMP_PS_TWELVEBYTES) {
219  if (ffurl_read_complete(h, buf, 4) != 4)
220  return AVERROR(EIO);
221  written += 4;
222  extra = AV_RL32(buf);
223  }
224  }
225  }
226  if (ts_field == 0xFFFFFF) {
227  if (ffurl_read_complete(h, buf, 4) != 4)
228  return AVERROR(EIO);
229  timestamp = AV_RB32(buf);
230  } else {
231  timestamp = ts_field;
232  }
233  if (hdr != RTMP_PS_TWELVEBYTES)
234  timestamp += prev_pkt[channel_id].timestamp;
235 
236  if (prev_pkt[channel_id].read && size != prev_pkt[channel_id].size) {
237  av_log(h, AV_LOG_ERROR, "RTMP packet size mismatch %d != %d\n",
238  size, prev_pkt[channel_id].size);
239  ff_rtmp_packet_destroy(&prev_pkt[channel_id]);
240  prev_pkt[channel_id].read = 0;
241  return AVERROR_INVALIDDATA;
242  }
243 
244  if (!prev_pkt[channel_id].read) {
245  if ((ret = ff_rtmp_packet_create(p, channel_id, type, timestamp,
246  size)) < 0)
247  return ret;
248  p->read = written;
249  p->offset = 0;
250  prev_pkt[channel_id].ts_field = ts_field;
251  prev_pkt[channel_id].timestamp = timestamp;
252  } else {
253  // previous packet in this channel hasn't completed reading
254  RTMPPacket *prev = &prev_pkt[channel_id];
255  p->data = prev->data;
256  p->size = prev->size;
257  p->channel_id = prev->channel_id;
258  p->type = prev->type;
259  p->ts_field = prev->ts_field;
260  p->extra = prev->extra;
261  p->offset = prev->offset;
262  p->read = prev->read + written;
263  p->timestamp = prev->timestamp;
264  prev->data = NULL;
265  }
266  p->extra = extra;
267  // save history
268  prev_pkt[channel_id].channel_id = channel_id;
269  prev_pkt[channel_id].type = type;
270  prev_pkt[channel_id].size = size;
271  prev_pkt[channel_id].extra = extra;
272  size = size - p->offset;
273 
274  toread = FFMIN(size, chunk_size);
275  if (ffurl_read_complete(h, p->data + p->offset, toread) != toread) {
277  return AVERROR(EIO);
278  }
279  size -= toread;
280  p->read += toread;
281  p->offset += toread;
282 
283  if (size > 0) {
284  RTMPPacket *prev = &prev_pkt[channel_id];
285  prev->data = p->data;
286  prev->read = p->read;
287  prev->offset = p->offset;
288  p->data = NULL;
289  return AVERROR(EAGAIN);
290  }
291 
292  prev_pkt[channel_id].read = 0; // read complete; reset if needed
293  return p->read;
294 }
295 
297  RTMPPacket **prev_pkt, int *nb_prev_pkt,
298  uint8_t hdr)
299 {
300  while (1) {
301  int ret = rtmp_packet_read_one_chunk(h, p, chunk_size, prev_pkt,
302  nb_prev_pkt, hdr);
303  if (ret > 0 || ret != AVERROR(EAGAIN))
304  return ret;
305 
306  if (ffurl_read(h, &hdr, 1) != 1)
307  return AVERROR(EIO);
308  }
309 }
310 
312  int chunk_size, RTMPPacket **prev_pkt_ptr,
313  int *nb_prev_pkt)
314 {
315  uint8_t pkt_hdr[16], *p = pkt_hdr;
317  int off = 0;
318  int written = 0;
319  int ret;
320  RTMPPacket *prev_pkt;
321  int use_delta; // flag if using timestamp delta, not RTMP_PS_TWELVEBYTES
322  uint32_t timestamp; // full 32-bit timestamp or delta value
323 
324  if ((ret = ff_rtmp_check_alloc_array(prev_pkt_ptr, nb_prev_pkt,
325  pkt->channel_id)) < 0)
326  return ret;
327  prev_pkt = *prev_pkt_ptr;
328 
329  //if channel_id = 0, this is first presentation of prev_pkt, send full hdr.
330  use_delta = prev_pkt[pkt->channel_id].channel_id &&
331  pkt->extra == prev_pkt[pkt->channel_id].extra &&
332  pkt->timestamp >= prev_pkt[pkt->channel_id].timestamp;
333 
334  timestamp = pkt->timestamp;
335  if (use_delta) {
336  timestamp -= prev_pkt[pkt->channel_id].timestamp;
337  }
338  if (timestamp >= 0xFFFFFF) {
339  pkt->ts_field = 0xFFFFFF;
340  } else {
341  pkt->ts_field = timestamp;
342  }
343 
344  if (use_delta) {
345  if (pkt->type == prev_pkt[pkt->channel_id].type &&
346  pkt->size == prev_pkt[pkt->channel_id].size) {
348  if (pkt->ts_field == prev_pkt[pkt->channel_id].ts_field)
350  } else {
352  }
353  }
354 
355  if (pkt->channel_id < 64) {
356  bytestream_put_byte(&p, pkt->channel_id | (mode << 6));
357  } else if (pkt->channel_id < 64 + 256) {
358  bytestream_put_byte(&p, 0 | (mode << 6));
359  bytestream_put_byte(&p, pkt->channel_id - 64);
360  } else {
361  bytestream_put_byte(&p, 1 | (mode << 6));
362  bytestream_put_le16(&p, pkt->channel_id - 64);
363  }
364  if (mode != RTMP_PS_ONEBYTE) {
365  bytestream_put_be24(&p, pkt->ts_field);
366  if (mode != RTMP_PS_FOURBYTES) {
367  bytestream_put_be24(&p, pkt->size);
368  bytestream_put_byte(&p, pkt->type);
369  if (mode == RTMP_PS_TWELVEBYTES)
370  bytestream_put_le32(&p, pkt->extra);
371  }
372  }
373  if (pkt->ts_field == 0xFFFFFF)
374  bytestream_put_be32(&p, timestamp);
375  // save history
376  prev_pkt[pkt->channel_id].channel_id = pkt->channel_id;
377  prev_pkt[pkt->channel_id].type = pkt->type;
378  prev_pkt[pkt->channel_id].size = pkt->size;
379  prev_pkt[pkt->channel_id].timestamp = pkt->timestamp;
380  prev_pkt[pkt->channel_id].ts_field = pkt->ts_field;
381  prev_pkt[pkt->channel_id].extra = pkt->extra;
382 
383  // FIXME:
384  // Writing packets is currently not optimized to minimize system calls.
385  // Since system calls flush on exit which we cannot change in a system-independant way.
386  // We should fix this behavior and by writing packets in a single or in as few as possible system calls.
387  // Protocols like TCP and RTMP should benefit from this when enabling TCP_NODELAY.
388 
389  if ((ret = ffurl_write(h, pkt_hdr, p - pkt_hdr)) < 0)
390  return ret;
391  written = p - pkt_hdr + pkt->size;
392  while (off < pkt->size) {
393  int towrite = FFMIN(chunk_size, pkt->size - off);
394  if ((ret = ffurl_write(h, pkt->data + off, towrite)) < 0)
395  return ret;
396  off += towrite;
397  if (off < pkt->size) {
398  uint8_t marker = 0xC0 | pkt->channel_id;
399  if ((ret = ffurl_write(h, &marker, 1)) < 0)
400  return ret;
401  written++;
402  if (pkt->ts_field == 0xFFFFFF) {
403  uint8_t ts_header[4];
404  AV_WB32(ts_header, timestamp);
405  if ((ret = ffurl_write(h, ts_header, 4)) < 0)
406  return ret;
407  written += 4;
408  }
409  }
410  }
411  return written;
412 }
413 
415  int timestamp, int size)
416 {
417  if (size) {
418  pkt->data = av_realloc(NULL, size);
419  if (!pkt->data)
420  return AVERROR(ENOMEM);
421  }
422  pkt->size = size;
423  pkt->channel_id = channel_id;
424  pkt->type = type;
425  pkt->timestamp = timestamp;
426  pkt->extra = 0;
427  pkt->ts_field = 0;
428 
429  return 0;
430 }
431 
433 {
434  if (!pkt)
435  return;
436  av_freep(&pkt->data);
437  pkt->size = 0;
438 }
439 
441 {
443  unsigned nb = -1;
444  int parse_key = 1;
445 
446  if (bytestream2_get_bytes_left(gb) < 1)
447  return -1;
448 
449  type = bytestream2_get_byte(gb);
450  switch (type) {
452  bytestream2_get_be64(gb);
453  return 0;
454  case AMF_DATA_TYPE_BOOL:
455  bytestream2_get_byte(gb);
456  return 0;
458  bytestream2_skip(gb, bytestream2_get_be16(gb));
459  return 0;
461  bytestream2_skip(gb, bytestream2_get_be32(gb));
462  return 0;
463  case AMF_DATA_TYPE_NULL:
464  return 0;
465  case AMF_DATA_TYPE_DATE:
466  bytestream2_skip(gb, 10);
467  return 0;
468  case AMF_DATA_TYPE_ARRAY:
469  parse_key = 0;
471  nb = bytestream2_get_be32(gb);
473  while (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY) {
474  int t;
475  if (parse_key) {
476  int size = bytestream2_get_be16(gb);
477  if (!size) {
478  bytestream2_get_byte(gb);
479  break;
480  }
481  if (size < 0 || size >= bytestream2_get_bytes_left(gb))
482  return -1;
483  bytestream2_skip(gb, size);
484  }
485  t = amf_tag_skip(gb);
486  if (t < 0 || bytestream2_get_bytes_left(gb) <= 0)
487  return -1;
488  }
489  return 0;
490  case AMF_DATA_TYPE_OBJECT_END: return 0;
491  default: return -1;
492  }
493 }
494 
495 int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
496 {
497  GetByteContext gb;
498  int ret;
499 
500  if (data >= data_end)
501  return -1;
502 
503  bytestream2_init(&gb, data, data_end - data);
504 
505  ret = amf_tag_skip(&gb);
506  if (ret < 0 || bytestream2_get_bytes_left(&gb) <= 0)
507  return -1;
508  av_assert0(bytestream2_tell(&gb) >= 0 && bytestream2_tell(&gb) <= data_end - data);
509  return bytestream2_tell(&gb);
510 }
511 
513  const uint8_t *name, uint8_t *dst, int dst_size)
514 {
515  int namelen = strlen(name);
516  int len;
517 
518  while (bytestream2_peek_byte(gb) != AMF_DATA_TYPE_OBJECT && bytestream2_get_bytes_left(gb) > 0) {
519  int ret = amf_tag_skip(gb);
520  if (ret < 0)
521  return -1;
522  }
523  if (bytestream2_get_bytes_left(gb) < 3)
524  return -1;
525  bytestream2_get_byte(gb);
526 
527  for (;;) {
528  int size = bytestream2_get_be16(gb);
529  if (!size)
530  break;
531  if (size < 0 || size >= bytestream2_get_bytes_left(gb))
532  return -1;
533  bytestream2_skip(gb, size);
534  if (size == namelen && !memcmp(gb->buffer-size, name, namelen)) {
535  switch (bytestream2_get_byte(gb)) {
537  snprintf(dst, dst_size, "%g", av_int2double(bytestream2_get_be64(gb)));
538  break;
539  case AMF_DATA_TYPE_BOOL:
540  snprintf(dst, dst_size, "%s", bytestream2_get_byte(gb) ? "true" : "false");
541  break;
543  len = bytestream2_get_be16(gb);
544  if (dst_size < 1)
545  return -1;
546  if (dst_size < len + 1)
547  len = dst_size - 1;
548  bytestream2_get_buffer(gb, dst, len);
549  dst[len] = 0;
550  break;
551  default:
552  return -1;
553  }
554  return 0;
555  }
556  len = amf_tag_skip(gb);
557  if (len < 0 || bytestream2_get_bytes_left(gb) <= 0)
558  return -1;
559  }
560  return -1;
561 }
562 
563 int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end,
564  const uint8_t *name, uint8_t *dst, int dst_size)
565 {
566  GetByteContext gb;
567 
568  if (data >= data_end)
569  return -1;
570 
571  bytestream2_init(&gb, data, data_end - data);
572 
573  return amf_get_field_value2(&gb, name, dst, dst_size);
574 }
575 
576 #ifdef DEBUG
577 static const char* rtmp_packet_type(int type)
578 {
579  switch (type) {
580  case RTMP_PT_CHUNK_SIZE: return "chunk size";
581  case RTMP_PT_BYTES_READ: return "bytes read";
582  case RTMP_PT_USER_CONTROL: return "user control";
583  case RTMP_PT_WINDOW_ACK_SIZE: return "window acknowledgement size";
584  case RTMP_PT_SET_PEER_BW: return "set peer bandwidth";
585  case RTMP_PT_AUDIO: return "audio packet";
586  case RTMP_PT_VIDEO: return "video packet";
587  case RTMP_PT_FLEX_STREAM: return "Flex shared stream";
588  case RTMP_PT_FLEX_OBJECT: return "Flex shared object";
589  case RTMP_PT_FLEX_MESSAGE: return "Flex shared message";
590  case RTMP_PT_NOTIFY: return "notification";
591  case RTMP_PT_SHARED_OBJ: return "shared object";
592  case RTMP_PT_INVOKE: return "invoke";
593  case RTMP_PT_METADATA: return "metadata";
594  default: return "unknown";
595  }
596 }
597 
598 static void amf_tag_contents(void *ctx, const uint8_t *data,
599  const uint8_t *data_end)
600 {
601  unsigned int size, nb = -1;
602  char buf[1024];
604  int parse_key = 1;
605 
606  if (data >= data_end)
607  return;
608  switch ((type = *data++)) {
610  av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2double(AV_RB64(data)));
611  return;
612  case AMF_DATA_TYPE_BOOL:
613  av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data);
614  return;
617  if (type == AMF_DATA_TYPE_STRING) {
618  size = bytestream_get_be16(&data);
619  } else {
620  size = bytestream_get_be32(&data);
621  }
622  size = FFMIN(size, sizeof(buf) - 1);
623  memcpy(buf, data, size);
624  buf[size] = 0;
625  av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf);
626  return;
627  case AMF_DATA_TYPE_NULL:
628  av_log(ctx, AV_LOG_DEBUG, " NULL\n");
629  return;
630  case AMF_DATA_TYPE_ARRAY:
631  parse_key = 0;
633  nb = bytestream_get_be32(&data);
635  av_log(ctx, AV_LOG_DEBUG, " {\n");
636  while (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY) {
637  int t;
638  if (parse_key) {
639  size = bytestream_get_be16(&data);
640  size = FFMIN(size, sizeof(buf) - 1);
641  if (!size) {
642  av_log(ctx, AV_LOG_DEBUG, " }\n");
643  data++;
644  break;
645  }
646  memcpy(buf, data, size);
647  buf[size] = 0;
648  if (size >= data_end - data)
649  return;
650  data += size;
651  av_log(ctx, AV_LOG_DEBUG, " %s: ", buf);
652  }
653  amf_tag_contents(ctx, data, data_end);
654  t = ff_amf_tag_size(data, data_end);
655  if (t < 0 || t >= data_end - data)
656  return;
657  data += t;
658  }
659  return;
661  av_log(ctx, AV_LOG_DEBUG, " }\n");
662  return;
663  default:
664  return;
665  }
666 }
667 
668 void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
669 {
670  av_log(ctx, AV_LOG_DEBUG, "RTMP packet type '%s'(%d) for channel %d, timestamp %d, extra field %d size %d\n",
671  rtmp_packet_type(p->type), p->type, p->channel_id, p->timestamp, p->extra, p->size);
672  if (p->type == RTMP_PT_INVOKE || p->type == RTMP_PT_NOTIFY) {
673  uint8_t *src = p->data, *src_end = p->data + p->size;
674  while (src < src_end) {
675  int sz;
676  amf_tag_contents(ctx, src, src_end);
677  sz = ff_amf_tag_size(src, src_end);
678  if (sz < 0)
679  break;
680  src += sz;
681  }
682  } else if (p->type == RTMP_PT_WINDOW_ACK_SIZE) {
683  av_log(ctx, AV_LOG_DEBUG, "Window acknowledgement size = %d\n", AV_RB32(p->data));
684  } else if (p->type == RTMP_PT_SET_PEER_BW) {
685  av_log(ctx, AV_LOG_DEBUG, "Set Peer BW = %d\n", AV_RB32(p->data));
686  } else if (p->type != RTMP_PT_AUDIO && p->type != RTMP_PT_VIDEO && p->type != RTMP_PT_METADATA) {
687  int i;
688  for (i = 0; i < p->size; i++)
689  av_log(ctx, AV_LOG_DEBUG, " %02X", p->data[i]);
690  av_log(ctx, AV_LOG_DEBUG, "\n");
691  }
692 }
693 #endif
694 
695 int ff_amf_match_string(const uint8_t *data, int size, const char *str)
696 {
697  int len = strlen(str);
698  int amf_len, type;
699 
700  if (size < 1)
701  return 0;
702 
703  type = *data++;
704 
707  return 0;
708 
710  if ((size -= 4 + 1) < 0)
711  return 0;
712  amf_len = bytestream_get_be32(&data);
713  } else {
714  if ((size -= 2 + 1) < 0)
715  return 0;
716  amf_len = bytestream_get_be16(&data);
717  }
718 
719  if (amf_len > size)
720  return 0;
721 
722  if (amf_len != len)
723  return 0;
724 
725  return !memcmp(data, str, len);
726 }
RTMP_PT_METADATA
@ RTMP_PT_METADATA
FLV metadata.
Definition: rtmppkt.h:61
RTMP_PT_FLEX_MESSAGE
@ RTMP_PT_FLEX_MESSAGE
Flex shared message.
Definition: rtmppkt.h:57
AMF_DATA_TYPE_OBJECT_END
@ AMF_DATA_TYPE_OBJECT_END
Definition: flv.h:147
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
RTMP_PT_FLEX_OBJECT
@ RTMP_PT_FLEX_OBJECT
Flex shared object.
Definition: rtmppkt.h:56
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
RTMP_PT_SHARED_OBJ
@ RTMP_PT_SHARED_OBJ
shared object
Definition: rtmppkt.h:59
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
RTMP_PT_BYTES_READ
@ RTMP_PT_BYTES_READ
number of bytes read
Definition: rtmppkt.h:49
RTMPPacket::type
RTMPPacketType type
packet payload type
Definition: rtmppkt.h:79
GetByteContext
Definition: bytestream.h:33
av_int2double
static av_always_inline double av_int2double(uint64_t i)
Reinterpret a 64-bit integer as a double.
Definition: intfloat.h:60
RTMP_PT_NOTIFY
@ RTMP_PT_NOTIFY
some notification
Definition: rtmppkt.h:58
ffurl_write
static int ffurl_write(URLContext *h, const uint8_t *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: url.h:208
AVPacket::data
uint8_t * data
Definition: packet.h:491
data
const char data[16]
Definition: mxf.c:148
ff_amf_write_field_name
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:79
ff_amf_match_string
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:695
RTMP_PT_WINDOW_ACK_SIZE
@ RTMP_PT_WINDOW_ACK_SIZE
window acknowledgement size
Definition: rtmppkt.h:51
AMF_DATA_TYPE_DATE
@ AMF_DATA_TYPE_DATE
Definition: flv.h:149
RTMPPacket::extra
uint32_t extra
probably an additional channel ID used during streaming data
Definition: rtmppkt.h:82
intfloat.h
ff_rtmp_packet_read_internal
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:296
AMF_DATA_TYPE_OBJECT
@ AMF_DATA_TYPE_OBJECT
Definition: flv.h:142
ff_amf_write_bool
void ff_amf_write_bool(uint8_t **dst, int val)
Write boolean value in AMF format to buffer.
Definition: rtmppkt.c:31
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
ff_rtmp_packet_read
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:157
val
static double val(void *priv, double ch)
Definition: aeval.c:78
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
ff_amf_get_string
int ff_amf_get_string(GetByteContext *bc, uint8_t *str, int strsize, int *length)
Get AMF string value.
Definition: rtmppkt.c:103
amf_get_field_value2
static int amf_get_field_value2(GetByteContext *gb, const uint8_t *name, uint8_t *dst, int dst_size)
Definition: rtmppkt.c:512
AMFDataType
AMFDataType
Definition: flv.h:138
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
ff_amf_write_string
void ff_amf_write_string(uint8_t **dst, const char *str)
Write string in AMF format to buffer.
Definition: rtmppkt.c:49
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:215
GetByteContext::buffer
const uint8_t * buffer
Definition: bytestream.h:34
RTMPPacket::read
int read
amount read, including headers
Definition: rtmppkt.h:86
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
parse_key
static int parse_key(DBEContext *s)
Definition: dolby_e.c:626
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
NULL
#define NULL
Definition: coverity.c:32
RTMPPacket
structure for holding RTMP packets
Definition: rtmppkt.h:77
RTMPPacketType
RTMPPacketType
known RTMP packet types
Definition: rtmppkt.h:47
ff_amf_write_object_end
void ff_amf_write_object_end(uint8_t **dst)
Write marker for end of AMF object to buffer.
Definition: rtmppkt.c:85
AMF_DATA_TYPE_BOOL
@ AMF_DATA_TYPE_BOOL
Definition: flv.h:140
ff_rtmp_packet_destroy
void ff_rtmp_packet_destroy(RTMPPacket *pkt)
Free RTMP packet.
Definition: rtmppkt.c:432
amf_tag_skip
static int amf_tag_skip(GetByteContext *gb)
Definition: rtmppkt.c:440
bytestream2_get_buffer
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
flv.h
AMF_DATA_TYPE_ARRAY
@ AMF_DATA_TYPE_ARRAY
Definition: flv.h:148
RTMP_PT_USER_CONTROL
@ RTMP_PT_USER_CONTROL
user control
Definition: rtmppkt.h:50
ff_rtmp_packet_write
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:311
RTMPPacket::size
int size
packet payload size
Definition: rtmppkt.h:84
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
bytestream2_tell
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:192
AV_WB32
#define AV_WB32(p, v)
Definition: intreadwrite.h:417
AVPacket::size
int size
Definition: packet.h:492
ff_amf_get_field_value
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:563
RTMP_PT_INVOKE
@ RTMP_PT_INVOKE
invoke some stream action
Definition: rtmppkt.h:60
size
int size
Definition: twinvq_data.h:10344
AV_RB32
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:96
ff_amf_write_null
void ff_amf_write_null(uint8_t **dst)
Write AMF NULL value to buffer.
Definition: rtmppkt.c:69
RTMPPacket::ts_field
uint32_t ts_field
24-bit timestamp or increment to the previous one, in milliseconds (latter only for media packets)....
Definition: rtmppkt.h:81
ff_rtmp_packet_dump
void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
Print information and contents of RTMP packet.
rtmp_packet_read_one_chunk
static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket **prev_pkt_ptr, int *nb_prev_pkt, uint8_t hdr)
Definition: rtmppkt.c:169
ff_rtmp_packet_create
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:414
ff_rtmp_check_alloc_array
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:136
av_double2int
static av_always_inline uint64_t av_double2int(double f)
Reinterpret a double as a 64-bit integer.
Definition: intfloat.h:70
rtmppkt.h
bytestream_put_buffer
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition: bytestream.h:372
URLContext
Definition: url.h:37
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
RTMPPacket::timestamp
uint32_t timestamp
packet full timestamp
Definition: rtmppkt.h:80
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
url.h
len
int len
Definition: vorbis_enc_data.h:426
RTMP_PT_SET_PEER_BW
@ RTMP_PT_SET_PEER_BW
peer bandwidth
Definition: rtmppkt.h:52
AMF_DATA_TYPE_MIXEDARRAY
@ AMF_DATA_TYPE_MIXEDARRAY
Definition: flv.h:146
AMF_DATA_TYPE_STRING
@ AMF_DATA_TYPE_STRING
Definition: flv.h:141
ff_amf_write_string2
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:56
RTMPPacket::offset
int offset
amount of data read so far
Definition: rtmppkt.h:85
ret
ret
Definition: filter_design.txt:187
avformat.h
ff_amf_read_number
int ff_amf_read_number(GetByteContext *bc, double *val)
Read AMF number value.
Definition: rtmppkt.c:93
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
ff_amf_write_number
void ff_amf_write_number(uint8_t **dst, double val)
Write number in AMF format to buffer.
Definition: rtmppkt.c:37
RTMPPacket::channel_id
int channel_id
RTMP channel ID (nothing to do with audio/video channels though)
Definition: rtmppkt.h:78
ff_amf_write_array_start
void ff_amf_write_array_start(uint8_t **dst, uint32_t length)
Write marker and length for AMF array to buffer.
Definition: rtmppkt.c:43
RTMP_PS_EIGHTBYTES
@ RTMP_PS_EIGHTBYTES
packet has 8-byte header
Definition: rtmppkt.h:69
RTMPPacket::data
uint8_t * data
packet payload
Definition: rtmppkt.h:83
mode
mode
Definition: ebur128.h:83
ff_amf_write_object_start
void ff_amf_write_object_start(uint8_t **dst)
Write marker for AMF object to buffer.
Definition: rtmppkt.c:74
AMF_DATA_TYPE_LONG_STRING
@ AMF_DATA_TYPE_LONG_STRING
Definition: flv.h:150
AMF_DATA_TYPE_NUMBER
@ AMF_DATA_TYPE_NUMBER
Definition: flv.h:139
ffurl_read_complete
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:404
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
RTMP_PS_ONEBYTE
@ RTMP_PS_ONEBYTE
packet is really a next chunk of a packet
Definition: rtmppkt.h:71
bytestream.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
h
h
Definition: vp9dsp_template.c:2038
avstring.h
RTMP_PT_AUDIO
@ RTMP_PT_AUDIO
audio packet
Definition: rtmppkt.h:53
AV_RB24
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_RB24
Definition: bytestream.h:97
ff_amf_read_null
int ff_amf_read_null(GetByteContext *bc)
Read AMF NULL value.
Definition: rtmppkt.c:129
RTMP_PS_TWELVEBYTES
@ RTMP_PS_TWELVEBYTES
packet has 12-byte header
Definition: rtmppkt.h:68
snprintf
#define snprintf
Definition: snprintf.h:34
RTMP_PT_VIDEO
@ RTMP_PT_VIDEO
video packet
Definition: rtmppkt.h:54
RTMP_PS_FOURBYTES
@ RTMP_PS_FOURBYTES
packet has 4-byte header
Definition: rtmppkt.h:70
AV_RB64
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_RB64
Definition: bytestream.h:95
RTMP_PT_FLEX_STREAM
@ RTMP_PT_FLEX_STREAM
Flex shared stream.
Definition: rtmppkt.h:55
channel
channel
Definition: ebur128.h:39
read
static uint32_t BS_FUNC() read(BSCTX *bc, unsigned int n)
Return n bits from the buffer, n has to be in the 0-32 range.
Definition: bitstream_template.h:231
AMF_DATA_TYPE_NULL
@ AMF_DATA_TYPE_NULL
Definition: flv.h:143
ff_amf_tag_size
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:495
av_realloc
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:153
ffurl_read
static int ffurl_read(URLContext *h, uint8_t *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.
Definition: url.h:183
RTMP_PT_CHUNK_SIZE
@ RTMP_PT_CHUNK_SIZE
chunk size change
Definition: rtmppkt.h:48
ff_amf_read_string
int ff_amf_read_string(GetByteContext *bc, uint8_t *str, int strsize, int *length)
Read AMF string value.
Definition: rtmppkt.c:121