Skip to content
Snippets Groups Projects
Commit cfac91fe authored by Kostya Shishkov's avatar Kostya Shishkov
Browse files

Dump RTMP packet contents in debug mode

Originally committed as revision 20799 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent f8caa544
No related branches found
No related tags found
No related merge requests found
......@@ -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");
}
}
......@@ -128,6 +128,14 @@ int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
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
......
......@@ -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) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment