Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.  
  63. void ff_amf_write_null(uint8_t **dst)
  64. {
  65.     bytestream_put_byte(dst, AMF_DATA_TYPE_NULL);
  66. }
  67.  
  68. void ff_amf_write_object_start(uint8_t **dst)
  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.  
  79. void ff_amf_write_object_end(uint8_t **dst)
  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.  
  87. int ff_amf_read_bool(GetByteContext *bc, int *val)
  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.  
  95. int ff_amf_read_number(GetByteContext *bc, double *val)
  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.  
  105. int ff_amf_get_string(GetByteContext *bc, uint8_t *str,
  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) {
  115.         av_log(NULL, AV_LOG_WARNING,
  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.  
  123. int ff_amf_read_string(GetByteContext *bc, uint8_t *str,
  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.  
  131. int ff_amf_read_null(GetByteContext *bc)
  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.  
  159. int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
  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.  
  171. static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
  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) {
  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) {
  270.         ff_rtmp_packet_destroy(p);
  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.  
  290. int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size,
  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.  
  305. int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt,
  306.                          int chunk_size, RTMPPacket **prev_pkt_ptr,
  307.                          int *nb_prev_pkt)
  308. {
  309.     uint8_t pkt_hdr[16], *p = pkt_hdr;
  310.     int mode = RTMP_PS_TWELVEBYTES;
  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.  
  402. int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type,
  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.  
  420. void ff_rtmp_packet_destroy(RTMPPacket *pkt)
  421. {
  422.     if (!pkt)
  423.         return;
  424.     av_freep(&pkt->data);
  425.     pkt->size = 0;
  426. }
  427.  
  428. int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
  429. {
  430.     const uint8_t *base = data;
  431.     AMFDataType type;
  432.     unsigned nb   = -1;
  433.     int parse_key = 1;
  434.  
  435.     if (data >= data_end)
  436.         return -1;
  437.     switch ((type = *data++)) {
  438.     case AMF_DATA_TYPE_NUMBER:      return 9;
  439.     case AMF_DATA_TYPE_BOOL:        return 2;
  440.     case AMF_DATA_TYPE_STRING:      return 3 + AV_RB16(data);
  441.     case AMF_DATA_TYPE_LONG_STRING: return 5 + AV_RB32(data);
  442.     case AMF_DATA_TYPE_NULL:        return 1;
  443.     case AMF_DATA_TYPE_DATE:        return 11;
  444.     case AMF_DATA_TYPE_ARRAY:
  445.         parse_key = 0;
  446.     case AMF_DATA_TYPE_MIXEDARRAY:
  447.         nb = bytestream_get_be32(&data);
  448.     case AMF_DATA_TYPE_OBJECT:
  449.         while (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY) {
  450.             int t;
  451.             if (parse_key) {
  452.                 int size = bytestream_get_be16(&data);
  453.                 if (!size) {
  454.                     data++;
  455.                     break;
  456.                 }
  457.                 if (size < 0 || size >= data_end - data)
  458.                     return -1;
  459.                 data += size;
  460.             }
  461.             t = ff_amf_tag_size(data, data_end);
  462.             if (t < 0 || t >= data_end - data)
  463.                 return -1;
  464.             data += t;
  465.         }
  466.         return data - base;
  467.     case AMF_DATA_TYPE_OBJECT_END:  return 1;
  468.     default:                        return -1;
  469.     }
  470. }
  471.  
  472. int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end,
  473.                            const uint8_t *name, uint8_t *dst, int dst_size)
  474. {
  475.     int namelen = strlen(name);
  476.     int len;
  477.  
  478.     while (*data != AMF_DATA_TYPE_OBJECT && data < data_end) {
  479.         len = ff_amf_tag_size(data, data_end);
  480.         if (len < 0)
  481.             len = data_end - data;
  482.         data += len;
  483.     }
  484.     if (data_end - data < 3)
  485.         return -1;
  486.     data++;
  487.     for (;;) {
  488.         int size = bytestream_get_be16(&data);
  489.         if (!size)
  490.             break;
  491.         if (size < 0 || size >= data_end - data)
  492.             return -1;
  493.         data += size;
  494.         if (size == namelen && !memcmp(data-size, name, namelen)) {
  495.             switch (*data++) {
  496.             case AMF_DATA_TYPE_NUMBER:
  497.                 snprintf(dst, dst_size, "%g", av_int2double(AV_RB64(data)));
  498.                 break;
  499.             case AMF_DATA_TYPE_BOOL:
  500.                 snprintf(dst, dst_size, "%s", *data ? "true" : "false");
  501.                 break;
  502.             case AMF_DATA_TYPE_STRING:
  503.                 len = bytestream_get_be16(&data);
  504.                 av_strlcpy(dst, data, FFMIN(len+1, dst_size));
  505.                 break;
  506.             default:
  507.                 return -1;
  508.             }
  509.             return 0;
  510.         }
  511.         len = ff_amf_tag_size(data, data_end);
  512.         if (len < 0 || len >= data_end - data)
  513.             return -1;
  514.         data += len;
  515.     }
  516.     return -1;
  517. }
  518.  
  519. static const char* rtmp_packet_type(int type)
  520. {
  521.     switch (type) {
  522.     case RTMP_PT_CHUNK_SIZE:     return "chunk size";
  523.     case RTMP_PT_BYTES_READ:     return "bytes read";
  524.     case RTMP_PT_PING:           return "ping";
  525.     case RTMP_PT_SERVER_BW:      return "server bandwidth";
  526.     case RTMP_PT_CLIENT_BW:      return "client bandwidth";
  527.     case RTMP_PT_AUDIO:          return "audio packet";
  528.     case RTMP_PT_VIDEO:          return "video packet";
  529.     case RTMP_PT_FLEX_STREAM:    return "Flex shared stream";
  530.     case RTMP_PT_FLEX_OBJECT:    return "Flex shared object";
  531.     case RTMP_PT_FLEX_MESSAGE:   return "Flex shared message";
  532.     case RTMP_PT_NOTIFY:         return "notification";
  533.     case RTMP_PT_SHARED_OBJ:     return "shared object";
  534.     case RTMP_PT_INVOKE:         return "invoke";
  535.     case RTMP_PT_METADATA:       return "metadata";
  536.     default:                     return "unknown";
  537.     }
  538. }
  539.  
  540. static void amf_tag_contents(void *ctx, const uint8_t *data,
  541.                              const uint8_t *data_end)
  542. {
  543.     unsigned int size, nb = -1;
  544.     char buf[1024];
  545.     AMFDataType type;
  546.     int parse_key = 1;
  547.  
  548.     if (data >= data_end)
  549.         return;
  550.     switch ((type = *data++)) {
  551.     case AMF_DATA_TYPE_NUMBER:
  552.         av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2double(AV_RB64(data)));
  553.         return;
  554.     case AMF_DATA_TYPE_BOOL:
  555.         av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data);
  556.         return;
  557.     case AMF_DATA_TYPE_STRING:
  558.     case AMF_DATA_TYPE_LONG_STRING:
  559.         if (type == AMF_DATA_TYPE_STRING) {
  560.             size = bytestream_get_be16(&data);
  561.         } else {
  562.             size = bytestream_get_be32(&data);
  563.         }
  564.         size = FFMIN(size, sizeof(buf) - 1);
  565.         memcpy(buf, data, size);
  566.         buf[size] = 0;
  567.         av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf);
  568.         return;
  569.     case AMF_DATA_TYPE_NULL:
  570.         av_log(ctx, AV_LOG_DEBUG, " NULL\n");
  571.         return;
  572.     case AMF_DATA_TYPE_ARRAY:
  573.         parse_key = 0;
  574.     case AMF_DATA_TYPE_MIXEDARRAY:
  575.         nb = bytestream_get_be32(&data);
  576.     case AMF_DATA_TYPE_OBJECT:
  577.         av_log(ctx, AV_LOG_DEBUG, " {\n");
  578.         while (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY) {
  579.             int t;
  580.             if (parse_key) {
  581.                 size = bytestream_get_be16(&data);
  582.                 size = FFMIN(size, sizeof(buf) - 1);
  583.                 if (!size) {
  584.                     av_log(ctx, AV_LOG_DEBUG, " }\n");
  585.                     data++;
  586.                     break;
  587.                 }
  588.                 memcpy(buf, data, size);
  589.                 buf[size] = 0;
  590.                 if (size >= data_end - data)
  591.                     return;
  592.                 data += size;
  593.                 av_log(ctx, AV_LOG_DEBUG, "  %s: ", buf);
  594.             }
  595.             amf_tag_contents(ctx, data, data_end);
  596.             t = ff_amf_tag_size(data, data_end);
  597.             if (t < 0 || t >= data_end - data)
  598.                 return;
  599.             data += t;
  600.         }
  601.         return;
  602.     case AMF_DATA_TYPE_OBJECT_END:
  603.         av_log(ctx, AV_LOG_DEBUG, " }\n");
  604.         return;
  605.     default:
  606.         return;
  607.     }
  608. }
  609.  
  610. void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
  611. {
  612.     av_log(ctx, AV_LOG_DEBUG, "RTMP packet type '%s'(%d) for channel %d, timestamp %d, extra field %d size %d\n",
  613.            rtmp_packet_type(p->type), p->type, p->channel_id, p->timestamp, p->extra, p->size);
  614.     if (p->type == RTMP_PT_INVOKE || p->type == RTMP_PT_NOTIFY) {
  615.         uint8_t *src = p->data, *src_end = p->data + p->size;
  616.         while (src < src_end) {
  617.             int sz;
  618.             amf_tag_contents(ctx, src, src_end);
  619.             sz = ff_amf_tag_size(src, src_end);
  620.             if (sz < 0)
  621.                 break;
  622.             src += sz;
  623.         }
  624.     } else if (p->type == RTMP_PT_SERVER_BW){
  625.         av_log(ctx, AV_LOG_DEBUG, "Server BW = %d\n", AV_RB32(p->data));
  626.     } else if (p->type == RTMP_PT_CLIENT_BW){
  627.         av_log(ctx, AV_LOG_DEBUG, "Client BW = %d\n", AV_RB32(p->data));
  628.     } else if (p->type != RTMP_PT_AUDIO && p->type != RTMP_PT_VIDEO && p->type != RTMP_PT_METADATA) {
  629.         int i;
  630.         for (i = 0; i < p->size; i++)
  631.             av_log(ctx, AV_LOG_DEBUG, " %02X", p->data[i]);
  632.         av_log(ctx, AV_LOG_DEBUG, "\n");
  633.     }
  634. }
  635.  
  636. int ff_amf_match_string(const uint8_t *data, int size, const char *str)
  637. {
  638.     int len = strlen(str);
  639.     int amf_len, type;
  640.  
  641.     if (size < 1)
  642.         return 0;
  643.  
  644.     type = *data++;
  645.  
  646.     if (type != AMF_DATA_TYPE_LONG_STRING &&
  647.         type != AMF_DATA_TYPE_STRING)
  648.         return 0;
  649.  
  650.     if (type == AMF_DATA_TYPE_LONG_STRING) {
  651.         if ((size -= 4 + 1) < 0)
  652.             return 0;
  653.         amf_len = bytestream_get_be32(&data);
  654.     } else {
  655.         if ((size -= 2 + 1) < 0)
  656.             return 0;
  657.         amf_len = bytestream_get_be16(&data);
  658.     }
  659.  
  660.     if (amf_len > size)
  661.         return 0;
  662.  
  663.     if (amf_len != len)
  664.         return 0;
  665.  
  666.     return !memcmp(data, str, len);
  667. }
  668.