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