diff options
author | Kostya Shishkov <kostya.shishkov@gmail.com> | 2009-12-11 20:13:35 +0300 |
---|---|---|
committer | Kostya Shishkov <kostya.shishkov@gmail.com> | 2009-12-11 20:13:35 +0300 |
commit | cfac91fec3acfac8dc6b8d6a658abb98d2823002 (patch) | |
tree | 02b20163c45631adce9f95d235f7f9ced98b6d75 /libavformat | |
parent | f8caa5441b2e1a9b45f19415512a855ac482398f (diff) |
Dump RTMP packet contents in debug mode
Originally committed as revision 20799 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/rtmppkt.c | 110 | ||||
-rw-r--r-- | libavformat/rtmppkt.h | 8 | ||||
-rw-r--r-- | libavformat/rtmpproto.c | 6 |
3 files changed, 124 insertions, 0 deletions
diff --git a/libavformat/rtmppkt.c b/libavformat/rtmppkt.c index 4ee06bc341..058a1ca37e 100644 --- a/libavformat/rtmppkt.c +++ b/libavformat/rtmppkt.c @@ -322,3 +322,113 @@ int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end, } return -1; } + +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_AUDIO: return "audio packet"; + case RTMP_PT_VIDEO: return "video packet"; + case RTMP_PT_FLEX_STREAM: return "Flex shared stream"; + case RTMP_PT_FLEX_OBJECT: return "Flex shared object"; + case RTMP_PT_FLEX_MESSAGE: return "Flex shared message"; + case RTMP_PT_NOTIFY: return "notification"; + case RTMP_PT_SHARED_OBJ: return "shared object"; + case RTMP_PT_INVOKE: return "invoke"; + case RTMP_PT_METADATA: return "metadata"; + default: return "unknown"; + } +} + +static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end) +{ + const uint8_t *base = data; + int i, size; + char buf[1024]; + + if (data >= data_end) + return; + switch (*data++) { + case AMF_DATA_TYPE_NUMBER: + av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2dbl(AV_RB64(data))); + return; + case AMF_DATA_TYPE_BOOL: + av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data); + return; + case AMF_DATA_TYPE_STRING: + case AMF_DATA_TYPE_LONG_STRING: + if (data[-1] == AMF_DATA_TYPE_STRING) { + size = bytestream_get_be16(&data); + } else { + size = bytestream_get_be32(data); + } + size = FFMIN(size, 1023); + memcpy(buf, data, size); + buf[size] = 0; + av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf); + return; + case AMF_DATA_TYPE_NULL: + av_log(ctx, AV_LOG_DEBUG, " NULL\n"); + return; + case AMF_DATA_TYPE_ARRAY: + data += 4; + case AMF_DATA_TYPE_OBJECT: + av_log(ctx, AV_LOG_DEBUG, " {\n"); + for (;;) { + int size = bytestream_get_be16(&data); + int t; + memcpy(buf, data, size); + buf[size] = 0; + if (!size) { + av_log(ctx, AV_LOG_DEBUG, " }\n"); + data++; + break; + } + if (data + size >= data_end || data + size < data) + return; + data += size; + av_log(ctx, AV_LOG_DEBUG, " %s: ", buf); + ff_amf_tag_contents(ctx, data, data_end); + t = ff_amf_tag_size(data, data_end); + if (t < 0 || data + t >= data_end) + return; + data += t; + } + return; + case AMF_DATA_TYPE_OBJECT_END: + av_log(ctx, AV_LOG_DEBUG, " }\n"); + return; + default: + return; + } +} + +void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p) +{ + av_log(ctx, AV_LOG_DEBUG, "RTMP packet type '%s'(%d) for channel %d, timestamp %d, extra field %d size %d\n", + rtmp_packet_type(p->type), p->type, p->channel_id, p->timestamp, p->extra, p->data_size); + if (p->type == RTMP_PT_INVOKE || p->type == RTMP_PT_NOTIFY) { + uint8_t *src = p->data, *src_end = p->data + p->data_size; + while (src < src_end) { + int sz; + ff_amf_tag_contents(ctx, src, src_end); + sz = ff_amf_tag_size(src, src_end); + if (sz < 0) + 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_AUDIO && p->type != RTMP_PT_VIDEO && p->type != RTMP_PT_METADATA) { + int i; + for (i = 0; i < p->data_size; i++) + av_log(ctx, AV_LOG_DEBUG, " %02X", p->data[i]); + av_log(ctx, AV_LOG_DEBUG, "\n"); + } +} diff --git a/libavformat/rtmppkt.h b/libavformat/rtmppkt.h index df1dd05525..560165b560 100644 --- a/libavformat/rtmppkt.h +++ b/libavformat/rtmppkt.h @@ -129,6 +129,14 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket *prev_pkt); /** + * Prints information and contents of RTMP packet. + * + * @param h output context + * @param p packet to dump + */ +void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p); + +/** * @defgroup amffuncs functions used to work with AMF format (which is also used in .flv) * @see amf_* funcs in libavformat/flvdec.c * @{ diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 559a93f867..bf3ab9307a 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -43,6 +43,8 @@ #define LOG_CONTEXT s #endif +//#define DEBUG + /** RTMP protocol handler state */ typedef enum { STATE_START, ///< client has not done anything yet @@ -529,6 +531,10 @@ static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt) int i, t; const uint8_t *data_end = pkt->data + pkt->data_size; +#ifdef DEBUG + ff_rtmp_packet_dump(LOG_CONTEXT, pkt); +#endif + switch (pkt->type) { case RTMP_PT_CHUNK_SIZE: if (pkt->data_size != 4) { |