Commit cfac91fe authored by Kostya Shishkov's avatar Kostya Shishkov

Dump RTMP packet contents in debug mode

Originally committed as revision 20799 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent f8caa544
......@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment