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