pkt->size = 0;
}
-int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
+static int amf_tag_skip(GetByteContext *gb)
{
- const uint8_t *base = data;
AMFDataType type;
unsigned nb = -1;
int parse_key = 1;
- if (data >= data_end)
+ if (bytestream2_get_bytes_left(gb) < 1)
return -1;
- switch ((type = *data++)) {
- case AMF_DATA_TYPE_NUMBER: return 9;
- case AMF_DATA_TYPE_BOOL: return 2;
- case AMF_DATA_TYPE_STRING: return 3 + AV_RB16(data);
- case AMF_DATA_TYPE_LONG_STRING: return 5 + AV_RB32(data);
- case AMF_DATA_TYPE_NULL: return 1;
- case AMF_DATA_TYPE_DATE: return 11;
+
+ type = bytestream2_get_byte(gb);
+ switch (type) {
+ case AMF_DATA_TYPE_NUMBER:
+ bytestream2_get_be64(gb);
+ return 0;
+ case AMF_DATA_TYPE_BOOL:
+ bytestream2_get_byte(gb);
+ return 0;
+ case AMF_DATA_TYPE_STRING:
+ bytestream2_skip(gb, bytestream2_get_be16(gb));
+ return 0;
+ case AMF_DATA_TYPE_LONG_STRING:
+ bytestream2_skip(gb, bytestream2_get_be32(gb));
+ return 0;
+ case AMF_DATA_TYPE_NULL:
+ return 0;
+ case AMF_DATA_TYPE_DATE:
+ bytestream2_skip(gb, 10);
+ return 0;
case AMF_DATA_TYPE_ARRAY:
parse_key = 0;
case AMF_DATA_TYPE_MIXEDARRAY:
- nb = bytestream_get_be32(&data);
+ nb = bytestream2_get_be32(gb);
case AMF_DATA_TYPE_OBJECT:
while (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY) {
int t;
if (parse_key) {
- int size = bytestream_get_be16(&data);
+ int size = bytestream2_get_be16(gb);
if (!size) {
- data++;
+ bytestream2_get_byte(gb);
break;
}
- if (size < 0 || size >= data_end - data)
+ if (size < 0 || size >= bytestream2_get_bytes_left(gb))
return -1;
- data += size;
+ bytestream2_skip(gb, size);
}
- t = ff_amf_tag_size(data, data_end);
- if (t < 0 || t >= data_end - data)
+ t = amf_tag_skip(gb);
+ if (t < 0 || bytestream2_get_bytes_left(gb) <= 0)
return -1;
- data += t;
}
- return data - base;
- case AMF_DATA_TYPE_OBJECT_END: return 1;
+ return 0;
+ case AMF_DATA_TYPE_OBJECT_END: return 0;
default: return -1;
}
}
-int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end,
+int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
+{
+ GetByteContext gb;
+ int ret;
+
+ if (data >= data_end)
+ return -1;
+
+ bytestream2_init(&gb, data, data_end - data);
+
+ ret = amf_tag_skip(&gb);
+ if (ret < 0 || bytestream2_get_bytes_left(&gb) <= 0)
+ return -1;
+ av_assert0(bytestream2_tell(&gb) >= 0 && bytestream2_tell(&gb) <= data_end - data);
+ return bytestream2_tell(&gb);
+}
+
+static int amf_get_field_value2(GetByteContext *gb,
const uint8_t *name, uint8_t *dst, int dst_size)
{
int namelen = strlen(name);
int len;
- while (*data != AMF_DATA_TYPE_OBJECT && data < data_end) {
- len = ff_amf_tag_size(data, data_end);
- if (len < 0)
- len = data_end - data;
- data += len;
+ while (bytestream2_peek_byte(gb) != AMF_DATA_TYPE_OBJECT && bytestream2_get_bytes_left(gb) > 0) {
+ int ret = amf_tag_skip(gb);
+ if (ret < 0)
+ return -1;
}
- if (data_end - data < 3)
+ if (bytestream2_get_bytes_left(gb) < 3)
return -1;
- data++;
+ bytestream2_get_byte(gb);
+
for (;;) {
- int size = bytestream_get_be16(&data);
+ int size = bytestream2_get_be16(gb);
if (!size)
break;
- if (size < 0 || size >= data_end - data)
+ if (size < 0 || size >= bytestream2_get_bytes_left(gb))
return -1;
- data += size;
- if (size == namelen && !memcmp(data-size, name, namelen)) {
- switch (*data++) {
+ bytestream2_skip(gb, size);
+ if (size == namelen && !memcmp(gb->buffer-size, name, namelen)) {
+ switch (bytestream2_get_byte(gb)) {
case AMF_DATA_TYPE_NUMBER:
- snprintf(dst, dst_size, "%g", av_int2double(AV_RB64(data)));
+ snprintf(dst, dst_size, "%g", av_int2double(bytestream2_get_be64(gb)));
break;
case AMF_DATA_TYPE_BOOL:
- snprintf(dst, dst_size, "%s", *data ? "true" : "false");
+ snprintf(dst, dst_size, "%s", bytestream2_get_byte(gb) ? "true" : "false");
break;
case AMF_DATA_TYPE_STRING:
- len = bytestream_get_be16(&data);
- av_strlcpy(dst, data, FFMIN(len+1, dst_size));
+ len = bytestream2_get_be16(gb);
+ if (dst_size < 1)
+ return -1;
+ if (dst_size < len + 1)
+ len = dst_size - 1;
+ bytestream2_get_buffer(gb, dst, len);
+ dst[len] = 0;
break;
default:
return -1;
}
return 0;
}
- len = ff_amf_tag_size(data, data_end);
- if (len < 0 || len >= data_end - data)
+ len = amf_tag_skip(gb);
+ if (len < 0 || bytestream2_get_bytes_left(gb) <= 0)
return -1;
- data += len;
}
return -1;
}
+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)
+{
+ GetByteContext gb;
+
+ if (data >= data_end)
+ return -1;
+
+ bytestream2_init(&gb, data, data_end - data);
+
+ return amf_get_field_value2(&gb, name, dst, dst_size);
+}
+
static const char* rtmp_packet_type(int type)
{
switch (type) {
case RTMP_PT_CHUNK_SIZE: return "chunk size";
case RTMP_PT_BYTES_READ: return "bytes read";
- case RTMP_PT_PING: return "ping";
- case RTMP_PT_SERVER_BW: return "server bandwidth";
- case RTMP_PT_CLIENT_BW: return "client bandwidth";
+ case RTMP_PT_USER_CONTROL: return "user control";
+ case RTMP_PT_WINDOW_ACK_SIZE: return "window acknowledgement size";
+ case RTMP_PT_SET_PEER_BW: return "set peer bandwidth";
case RTMP_PT_AUDIO: return "audio packet";
case RTMP_PT_VIDEO: return "video packet";
case RTMP_PT_FLEX_STREAM: return "Flex shared stream";
break;
src += sz;
}
- } else if (p->type == RTMP_PT_SERVER_BW){
- av_log(ctx, AV_LOG_DEBUG, "Server BW = %d\n", AV_RB32(p->data));
- } else if (p->type == RTMP_PT_CLIENT_BW){
- av_log(ctx, AV_LOG_DEBUG, "Client BW = %d\n", AV_RB32(p->data));
+ } else if (p->type == RTMP_PT_WINDOW_ACK_SIZE) {
+ av_log(ctx, AV_LOG_DEBUG, "Window acknowledgement size = %d\n", AV_RB32(p->data));
+ } else if (p->type == RTMP_PT_SET_PEER_BW) {
+ av_log(ctx, AV_LOG_DEBUG, "Set Peer BW = %d\n", AV_RB32(p->data));
} else if (p->type != RTMP_PT_AUDIO && p->type != RTMP_PT_VIDEO && p->type != RTMP_PT_METADATA) {
int i;
for (i = 0; i < p->size; i++)