Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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_read_string(GetByteContext *bc, uint8_t *str,
  106.                        int strsize, int *length)
  107. {
  108.     int stringlen = 0;
  109.     int readsize;
  110.     if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_STRING)
  111.         return AVERROR_INVALIDDATA;
  112.     stringlen = bytestream2_get_be16(bc);
  113.     if (stringlen + 1 > strsize)
  114.         return AVERROR(EINVAL);
  115.     readsize = bytestream2_get_buffer(bc, str, stringlen);
  116.     if (readsize != stringlen) {
  117.         av_log(NULL, AV_LOG_WARNING,
  118.                "Unable to read as many bytes as AMF string signaled\n");
  119.     }
  120.     str[readsize] = '\0';
  121.     *length = FFMIN(stringlen, readsize);
  122.     return 0;
  123. }
  124.  
  125. int ff_amf_read_null(GetByteContext *bc)
  126. {
  127.     if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_NULL)
  128.         return AVERROR_INVALIDDATA;
  129.     return 0;
  130. }
  131.  
  132. int ff_rtmp_check_alloc_array(RTMPPacket **prev_pkt, int *nb_prev_pkt,
  133.                               int channel)
  134. {
  135.     int nb_alloc;
  136.     RTMPPacket *ptr;
  137.     if (channel < *nb_prev_pkt)
  138.         return 0;
  139.  
  140.     nb_alloc = channel + 16;
  141.     // This can't use the av_reallocp family of functions, since we
  142.     // would need to free each element in the array before the array
  143.     // itself is freed.
  144.     ptr = av_realloc_array(*prev_pkt, nb_alloc, sizeof(**prev_pkt));
  145.     if (!ptr)
  146.         return AVERROR(ENOMEM);
  147.     memset(ptr + *nb_prev_pkt, 0, (nb_alloc - *nb_prev_pkt) * sizeof(*ptr));
  148.     *prev_pkt = ptr;
  149.     *nb_prev_pkt = nb_alloc;
  150.     return 0;
  151. }
  152.  
  153. int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
  154.                         int chunk_size, RTMPPacket **prev_pkt, int *nb_prev_pkt)
  155. {
  156.     uint8_t hdr;
  157.  
  158.     if (ffurl_read(h, &hdr, 1) != 1)
  159.         return AVERROR(EIO);
  160.  
  161.     return ff_rtmp_packet_read_internal(h, p, chunk_size, prev_pkt,
  162.                                         nb_prev_pkt, hdr);
  163. }
  164.  
  165. static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
  166.                                       int chunk_size, RTMPPacket **prev_pkt_ptr,
  167.                                       int *nb_prev_pkt, uint8_t hdr)
  168. {
  169.  
  170.     uint8_t buf[16];
  171.     int channel_id, timestamp, size;
  172.     uint32_t extra = 0;
  173.     enum RTMPPacketType type;
  174.     int written = 0;
  175.     int ret, toread;
  176.     RTMPPacket *prev_pkt;
  177.  
  178.     written++;
  179.     channel_id = hdr & 0x3F;
  180.  
  181.     if (channel_id < 2) { //special case for channel number >= 64
  182.         buf[1] = 0;
  183.         if (ffurl_read_complete(h, buf, channel_id + 1) != channel_id + 1)
  184.             return AVERROR(EIO);
  185.         written += channel_id + 1;
  186.         channel_id = AV_RL16(buf) + 64;
  187.     }
  188.     if ((ret = ff_rtmp_check_alloc_array(prev_pkt_ptr, nb_prev_pkt,
  189.                                          channel_id)) < 0)
  190.         return ret;
  191.     prev_pkt = *prev_pkt_ptr;
  192.     size  = prev_pkt[channel_id].size;
  193.     type  = prev_pkt[channel_id].type;
  194.     extra = prev_pkt[channel_id].extra;
  195.  
  196.     hdr >>= 6;
  197.     if (hdr == RTMP_PS_ONEBYTE) {
  198.         timestamp = prev_pkt[channel_id].ts_delta;
  199.     } else {
  200.         if (ffurl_read_complete(h, buf, 3) != 3)
  201.             return AVERROR(EIO);
  202.         written += 3;
  203.         timestamp = AV_RB24(buf);
  204.         if (hdr != RTMP_PS_FOURBYTES) {
  205.             if (ffurl_read_complete(h, buf, 3) != 3)
  206.                 return AVERROR(EIO);
  207.             written += 3;
  208.             size = AV_RB24(buf);
  209.             if (ffurl_read_complete(h, buf, 1) != 1)
  210.                 return AVERROR(EIO);
  211.             written++;
  212.             type = buf[0];
  213.             if (hdr == RTMP_PS_TWELVEBYTES) {
  214.                 if (ffurl_read_complete(h, buf, 4) != 4)
  215.                     return AVERROR(EIO);
  216.                 written += 4;
  217.                 extra = AV_RL32(buf);
  218.             }
  219.         }
  220.         if (timestamp == 0xFFFFFF) {
  221.             if (ffurl_read_complete(h, buf, 4) != 4)
  222.                 return AVERROR(EIO);
  223.             timestamp = AV_RB32(buf);
  224.         }
  225.     }
  226.     if (hdr != RTMP_PS_TWELVEBYTES)
  227.         timestamp += prev_pkt[channel_id].timestamp;
  228.  
  229.     if (!prev_pkt[channel_id].read) {
  230.         if ((ret = ff_rtmp_packet_create(p, channel_id, type, timestamp,
  231.                                          size)) < 0)
  232.             return ret;
  233.         p->read = written;
  234.         p->offset = 0;
  235.         prev_pkt[channel_id].ts_delta   = timestamp -
  236.                                           prev_pkt[channel_id].timestamp;
  237.         prev_pkt[channel_id].timestamp  = timestamp;
  238.     } else {
  239.         // previous packet in this channel hasn't completed reading
  240.         RTMPPacket *prev = &prev_pkt[channel_id];
  241.         p->data          = prev->data;
  242.         p->size          = prev->size;
  243.         p->channel_id    = prev->channel_id;
  244.         p->type          = prev->type;
  245.         p->ts_delta      = prev->ts_delta;
  246.         p->extra         = prev->extra;
  247.         p->offset        = prev->offset;
  248.         p->read          = prev->read + written;
  249.         p->timestamp     = prev->timestamp;
  250.         prev->data       = NULL;
  251.     }
  252.     p->extra = extra;
  253.     // save history
  254.     prev_pkt[channel_id].channel_id = channel_id;
  255.     prev_pkt[channel_id].type       = type;
  256.     prev_pkt[channel_id].size       = size;
  257.     prev_pkt[channel_id].extra      = extra;
  258.     size = size - p->offset;
  259.  
  260.     toread = FFMIN(size, chunk_size);
  261.     if (ffurl_read_complete(h, p->data + p->offset, toread) != toread) {
  262.         ff_rtmp_packet_destroy(p);
  263.         return AVERROR(EIO);
  264.     }
  265.     size      -= toread;
  266.     p->read   += toread;
  267.     p->offset += toread;
  268.  
  269.     if (size > 0) {
  270.        RTMPPacket *prev = &prev_pkt[channel_id];
  271.        prev->data = p->data;
  272.        prev->read = p->read;
  273.        prev->offset = p->offset;
  274.        return AVERROR(EAGAIN);
  275.     }
  276.  
  277.     prev_pkt[channel_id].read = 0; // read complete; reset if needed
  278.     return p->read;
  279. }
  280.  
  281. int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size,
  282.                                  RTMPPacket **prev_pkt, int *nb_prev_pkt,
  283.                                  uint8_t hdr)
  284. {
  285.     while (1) {
  286.         int ret = rtmp_packet_read_one_chunk(h, p, chunk_size, prev_pkt,
  287.                                              nb_prev_pkt, hdr);
  288.         if (ret > 0 || ret != AVERROR(EAGAIN))
  289.             return ret;
  290.  
  291.         if (ffurl_read(h, &hdr, 1) != 1)
  292.             return AVERROR(EIO);
  293.     }
  294. }
  295.  
  296. int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt,
  297.                          int chunk_size, RTMPPacket **prev_pkt_ptr,
  298.                          int *nb_prev_pkt)
  299. {
  300.     uint8_t pkt_hdr[16], *p = pkt_hdr;
  301.     int mode = RTMP_PS_TWELVEBYTES;
  302.     int off = 0;
  303.     int written = 0;
  304.     int ret;
  305.     RTMPPacket *prev_pkt;
  306.  
  307.     if ((ret = ff_rtmp_check_alloc_array(prev_pkt_ptr, nb_prev_pkt,
  308.                                          pkt->channel_id)) < 0)
  309.         return ret;
  310.     prev_pkt = *prev_pkt_ptr;
  311.  
  312.     pkt->ts_delta = pkt->timestamp - prev_pkt[pkt->channel_id].timestamp;
  313.  
  314.     //if channel_id = 0, this is first presentation of prev_pkt, send full hdr.
  315.     if (prev_pkt[pkt->channel_id].channel_id &&
  316.         pkt->extra == prev_pkt[pkt->channel_id].extra) {
  317.         if (pkt->type == prev_pkt[pkt->channel_id].type &&
  318.             pkt->size == prev_pkt[pkt->channel_id].size) {
  319.             mode = RTMP_PS_FOURBYTES;
  320.             if (pkt->ts_delta == prev_pkt[pkt->channel_id].ts_delta)
  321.                 mode = RTMP_PS_ONEBYTE;
  322.         } else {
  323.             mode = RTMP_PS_EIGHTBYTES;
  324.         }
  325.     }
  326.  
  327.     if (pkt->channel_id < 64) {
  328.         bytestream_put_byte(&p, pkt->channel_id | (mode << 6));
  329.     } else if (pkt->channel_id < 64 + 256) {
  330.         bytestream_put_byte(&p, 0               | (mode << 6));
  331.         bytestream_put_byte(&p, pkt->channel_id - 64);
  332.     } else {
  333.         bytestream_put_byte(&p, 1               | (mode << 6));
  334.         bytestream_put_le16(&p, pkt->channel_id - 64);
  335.     }
  336.     if (mode != RTMP_PS_ONEBYTE) {
  337.         uint32_t timestamp = pkt->timestamp;
  338.         if (mode != RTMP_PS_TWELVEBYTES)
  339.             timestamp = pkt->ts_delta;
  340.         bytestream_put_be24(&p, timestamp >= 0xFFFFFF ? 0xFFFFFF : timestamp);
  341.         if (mode != RTMP_PS_FOURBYTES) {
  342.             bytestream_put_be24(&p, pkt->size);
  343.             bytestream_put_byte(&p, pkt->type);
  344.             if (mode == RTMP_PS_TWELVEBYTES)
  345.                 bytestream_put_le32(&p, pkt->extra);
  346.         }
  347.         if (timestamp >= 0xFFFFFF)
  348.             bytestream_put_be32(&p, timestamp);
  349.     }
  350.     // save history
  351.     prev_pkt[pkt->channel_id].channel_id = pkt->channel_id;
  352.     prev_pkt[pkt->channel_id].type       = pkt->type;
  353.     prev_pkt[pkt->channel_id].size       = pkt->size;
  354.     prev_pkt[pkt->channel_id].timestamp  = pkt->timestamp;
  355.     if (mode != RTMP_PS_TWELVEBYTES) {
  356.         prev_pkt[pkt->channel_id].ts_delta   = pkt->ts_delta;
  357.     } else {
  358.         prev_pkt[pkt->channel_id].ts_delta   = pkt->timestamp;
  359.     }
  360.     prev_pkt[pkt->channel_id].extra      = pkt->extra;
  361.  
  362.     if ((ret = ffurl_write(h, pkt_hdr, p - pkt_hdr)) < 0)
  363.         return ret;
  364.     written = p - pkt_hdr + pkt->size;
  365.     while (off < pkt->size) {
  366.         int towrite = FFMIN(chunk_size, pkt->size - off);
  367.         if ((ret = ffurl_write(h, pkt->data + off, towrite)) < 0)
  368.             return ret;
  369.         off += towrite;
  370.         if (off < pkt->size) {
  371.             uint8_t marker = 0xC0 | pkt->channel_id;
  372.             if ((ret = ffurl_write(h, &marker, 1)) < 0)
  373.                 return ret;
  374.             written++;
  375.         }
  376.     }
  377.     return written;
  378. }
  379.  
  380. int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type,
  381.                           int timestamp, int size)
  382. {
  383.     if (size) {
  384.         pkt->data = av_malloc(size);
  385.         if (!pkt->data)
  386.             return AVERROR(ENOMEM);
  387.     }
  388.     pkt->size       = size;
  389.     pkt->channel_id = channel_id;
  390.     pkt->type       = type;
  391.     pkt->timestamp  = timestamp;
  392.     pkt->extra      = 0;
  393.     pkt->ts_delta   = 0;
  394.  
  395.     return 0;
  396. }
  397.  
  398. void ff_rtmp_packet_destroy(RTMPPacket *pkt)
  399. {
  400.     if (!pkt)
  401.         return;
  402.     av_freep(&pkt->data);
  403.     pkt->size = 0;
  404. }
  405.  
  406. int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
  407. {
  408.     const uint8_t *base = data;
  409.     AMFDataType type;
  410.     unsigned nb   = -1;
  411.     int parse_key = 1;
  412.  
  413.     if (data >= data_end)
  414.         return -1;
  415.     switch ((type = *data++)) {
  416.     case AMF_DATA_TYPE_NUMBER:      return 9;
  417.     case AMF_DATA_TYPE_BOOL:        return 2;
  418.     case AMF_DATA_TYPE_STRING:      return 3 + AV_RB16(data);
  419.     case AMF_DATA_TYPE_LONG_STRING: return 5 + AV_RB32(data);
  420.     case AMF_DATA_TYPE_NULL:        return 1;
  421.     case AMF_DATA_TYPE_ARRAY:
  422.         parse_key = 0;
  423.     case AMF_DATA_TYPE_MIXEDARRAY:
  424.         nb = bytestream_get_be32(&data);
  425.     case AMF_DATA_TYPE_OBJECT:
  426.         while (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY) {
  427.             int t;
  428.             if (parse_key) {
  429.                 int size = bytestream_get_be16(&data);
  430.                 if (!size) {
  431.                     data++;
  432.                     break;
  433.                 }
  434.                 if (size < 0 || size >= data_end - data)
  435.                     return -1;
  436.                 data += size;
  437.             }
  438.             t = ff_amf_tag_size(data, data_end);
  439.             if (t < 0 || t >= data_end - data)
  440.                 return -1;
  441.             data += t;
  442.         }
  443.         return data - base;
  444.     case AMF_DATA_TYPE_OBJECT_END:  return 1;
  445.     default:                        return -1;
  446.     }
  447. }
  448.  
  449. int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end,
  450.                            const uint8_t *name, uint8_t *dst, int dst_size)
  451. {
  452.     int namelen = strlen(name);
  453.     int len;
  454.  
  455.     while (*data != AMF_DATA_TYPE_OBJECT && data < data_end) {
  456.         len = ff_amf_tag_size(data, data_end);
  457.         if (len < 0)
  458.             len = data_end - data;
  459.         data += len;
  460.     }
  461.     if (data_end - data < 3)
  462.         return -1;
  463.     data++;
  464.     for (;;) {
  465.         int size = bytestream_get_be16(&data);
  466.         if (!size)
  467.             break;
  468.         if (size < 0 || size >= data_end - data)
  469.             return -1;
  470.         data += size;
  471.         if (size == namelen && !memcmp(data-size, name, namelen)) {
  472.             switch (*data++) {
  473.             case AMF_DATA_TYPE_NUMBER:
  474.                 snprintf(dst, dst_size, "%g", av_int2double(AV_RB64(data)));
  475.                 break;
  476.             case AMF_DATA_TYPE_BOOL:
  477.                 snprintf(dst, dst_size, "%s", *data ? "true" : "false");
  478.                 break;
  479.             case AMF_DATA_TYPE_STRING:
  480.                 len = bytestream_get_be16(&data);
  481.                 av_strlcpy(dst, data, FFMIN(len+1, dst_size));
  482.                 break;
  483.             default:
  484.                 return -1;
  485.             }
  486.             return 0;
  487.         }
  488.         len = ff_amf_tag_size(data, data_end);
  489.         if (len < 0 || len >= data_end - data)
  490.             return -1;
  491.         data += len;
  492.     }
  493.     return -1;
  494. }
  495.  
  496. static const char* rtmp_packet_type(int type)
  497. {
  498.     switch (type) {
  499.     case RTMP_PT_CHUNK_SIZE:     return "chunk size";
  500.     case RTMP_PT_BYTES_READ:     return "bytes read";
  501.     case RTMP_PT_PING:           return "ping";
  502.     case RTMP_PT_SERVER_BW:      return "server bandwidth";
  503.     case RTMP_PT_CLIENT_BW:      return "client bandwidth";
  504.     case RTMP_PT_AUDIO:          return "audio packet";
  505.     case RTMP_PT_VIDEO:          return "video packet";
  506.     case RTMP_PT_FLEX_STREAM:    return "Flex shared stream";
  507.     case RTMP_PT_FLEX_OBJECT:    return "Flex shared object";
  508.     case RTMP_PT_FLEX_MESSAGE:   return "Flex shared message";
  509.     case RTMP_PT_NOTIFY:         return "notification";
  510.     case RTMP_PT_SHARED_OBJ:     return "shared object";
  511.     case RTMP_PT_INVOKE:         return "invoke";
  512.     case RTMP_PT_METADATA:       return "metadata";
  513.     default:                     return "unknown";
  514.     }
  515. }
  516.  
  517. static void amf_tag_contents(void *ctx, const uint8_t *data,
  518.                              const uint8_t *data_end)
  519. {
  520.     unsigned int size, nb = -1;
  521.     char buf[1024];
  522.     AMFDataType type;
  523.     int parse_key = 1;
  524.  
  525.     if (data >= data_end)
  526.         return;
  527.     switch ((type = *data++)) {
  528.     case AMF_DATA_TYPE_NUMBER:
  529.         av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2double(AV_RB64(data)));
  530.         return;
  531.     case AMF_DATA_TYPE_BOOL:
  532.         av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data);
  533.         return;
  534.     case AMF_DATA_TYPE_STRING:
  535.     case AMF_DATA_TYPE_LONG_STRING:
  536.         if (type == AMF_DATA_TYPE_STRING) {
  537.             size = bytestream_get_be16(&data);
  538.         } else {
  539.             size = bytestream_get_be32(&data);
  540.         }
  541.         size = FFMIN(size, sizeof(buf) - 1);
  542.         memcpy(buf, data, size);
  543.         buf[size] = 0;
  544.         av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf);
  545.         return;
  546.     case AMF_DATA_TYPE_NULL:
  547.         av_log(ctx, AV_LOG_DEBUG, " NULL\n");
  548.         return;
  549.     case AMF_DATA_TYPE_ARRAY:
  550.         parse_key = 0;
  551.     case AMF_DATA_TYPE_MIXEDARRAY:
  552.         nb = bytestream_get_be32(&data);
  553.     case AMF_DATA_TYPE_OBJECT:
  554.         av_log(ctx, AV_LOG_DEBUG, " {\n");
  555.         while (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY) {
  556.             int t;
  557.             if (parse_key) {
  558.                 size = bytestream_get_be16(&data);
  559.                 size = FFMIN(size, sizeof(buf) - 1);
  560.                 if (!size) {
  561.                     av_log(ctx, AV_LOG_DEBUG, " }\n");
  562.                     data++;
  563.                     break;
  564.                 }
  565.                 memcpy(buf, data, size);
  566.                 buf[size] = 0;
  567.                 if (size >= data_end - data)
  568.                     return;
  569.                 data += size;
  570.                 av_log(ctx, AV_LOG_DEBUG, "  %s: ", buf);
  571.             }
  572.             amf_tag_contents(ctx, data, data_end);
  573.             t = ff_amf_tag_size(data, data_end);
  574.             if (t < 0 || t >= data_end - data)
  575.                 return;
  576.             data += t;
  577.         }
  578.         return;
  579.     case AMF_DATA_TYPE_OBJECT_END:
  580.         av_log(ctx, AV_LOG_DEBUG, " }\n");
  581.         return;
  582.     default:
  583.         return;
  584.     }
  585. }
  586.  
  587. void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
  588. {
  589.     av_log(ctx, AV_LOG_DEBUG, "RTMP packet type '%s'(%d) for channel %d, timestamp %d, extra field %d size %d\n",
  590.            rtmp_packet_type(p->type), p->type, p->channel_id, p->timestamp, p->extra, p->size);
  591.     if (p->type == RTMP_PT_INVOKE || p->type == RTMP_PT_NOTIFY) {
  592.         uint8_t *src = p->data, *src_end = p->data + p->size;
  593.         while (src < src_end) {
  594.             int sz;
  595.             amf_tag_contents(ctx, src, src_end);
  596.             sz = ff_amf_tag_size(src, src_end);
  597.             if (sz < 0)
  598.                 break;
  599.             src += sz;
  600.         }
  601.     } else if (p->type == RTMP_PT_SERVER_BW){
  602.         av_log(ctx, AV_LOG_DEBUG, "Server BW = %d\n", AV_RB32(p->data));
  603.     } else if (p->type == RTMP_PT_CLIENT_BW){
  604.         av_log(ctx, AV_LOG_DEBUG, "Client BW = %d\n", AV_RB32(p->data));
  605.     } else if (p->type != RTMP_PT_AUDIO && p->type != RTMP_PT_VIDEO && p->type != RTMP_PT_METADATA) {
  606.         int i;
  607.         for (i = 0; i < p->size; i++)
  608.             av_log(ctx, AV_LOG_DEBUG, " %02X", p->data[i]);
  609.         av_log(ctx, AV_LOG_DEBUG, "\n");
  610.     }
  611. }
  612.  
  613. int ff_amf_match_string(const uint8_t *data, int size, const char *str)
  614. {
  615.     int len = strlen(str);
  616.     int amf_len, type;
  617.  
  618.     if (size < 1)
  619.         return 0;
  620.  
  621.     type = *data++;
  622.  
  623.     if (type != AMF_DATA_TYPE_LONG_STRING &&
  624.         type != AMF_DATA_TYPE_STRING)
  625.         return 0;
  626.  
  627.     if (type == AMF_DATA_TYPE_LONG_STRING) {
  628.         if ((size -= 4 + 1) < 0)
  629.             return 0;
  630.         amf_len = bytestream_get_be32(&data);
  631.     } else {
  632.         if ((size -= 2 + 1) < 0)
  633.             return 0;
  634.         amf_len = bytestream_get_be16(&data);
  635.     }
  636.  
  637.     if (amf_len > size)
  638.         return 0;
  639.  
  640.     if (amf_len != len)
  641.         return 0;
  642.  
  643.     return !memcmp(data, str, len);
  644. }
  645.