| @@ -322,3 +322,113 @@ int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end, · 321 unmodified lines |
| 322 | 322 | } |
| 323 | 323 | return -1; |
| 324 | 324 | } |
| 325 | + |
| 326 | +static const char* rtmp_packet_type(int type) |
| 327 | +{ |
| 328 | + switch (type) { |
| 329 | + case RTMP_PT_CHUNK_SIZE: return "chunk size"; |
| 330 | + case RTMP_PT_BYTES_READ: return "bytes read"; |
| 331 | + case RTMP_PT_PING: return "ping"; |
| 332 | + case RTMP_PT_SERVER_BW: return "server bandwidth"; |
| 333 | + case RTMP_PT_CLIENT_BW: return "client bandwidth"; |
| 334 | + case RTMP_PT_AUDIO: return "audio packet"; |
| 335 | + case RTMP_PT_VIDEO: return "video packet"; |
| 336 | + case RTMP_PT_FLEX_STREAM: return "Flex shared stream"; |
| 337 | + case RTMP_PT_FLEX_OBJECT: return "Flex shared object"; |
| 338 | + case RTMP_PT_FLEX_MESSAGE: return "Flex shared message"; |
| 339 | + case RTMP_PT_NOTIFY: return "notification"; |
| 340 | + case RTMP_PT_SHARED_OBJ: return "shared object"; |
| 341 | + case RTMP_PT_INVOKE: return "invoke"; |
| 342 | + case RTMP_PT_METADATA: return "metadata"; |
| 343 | + default: return "unknown"; |
| 344 | + } |
| 345 | +} |
| 346 | + |
| 347 | +static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end) |
| 348 | +{ |
| 349 | + const uint8_t *base = data; |
| 350 | + int i, size; |
| 351 | + char buf[1024]; |
| 352 | + |
| 353 | + if (data >= data_end) |
| 354 | + return; |
| 355 | + switch (*data++) { |
| 356 | + case AMF_DATA_TYPE_NUMBER: |
| 357 | + av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2dbl(AV_RB64(data))); |
| 358 | + return; |
| 359 | + case AMF_DATA_TYPE_BOOL: |
| 360 | + av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data); |
| 361 | + return; |
| 362 | + case AMF_DATA_TYPE_STRING: |
| 363 | + case AMF_DATA_TYPE_LONG_STRING: |
| 364 | + if (data[-1] == AMF_DATA_TYPE_STRING) { |
| 365 | + size = bytestream_get_be16(&data); |
| 366 | + } else { |
| 367 | + size = bytestream_get_be32(data); |
| 368 | + } |
| 369 | + size = FFMIN(size, 1023); |
| 370 | + memcpy(buf, data, size); |
| 371 | + buf[size] = 0; |
| 372 | + av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf); |
| 373 | + return; |
| 374 | + case AMF_DATA_TYPE_NULL: |
| 375 | + av_log(ctx, AV_LOG_DEBUG, " NULL\n"); |
| 376 | + return; |
| 377 | + case AMF_DATA_TYPE_ARRAY: |
| 378 | + data += 4; |
| 379 | + case AMF_DATA_TYPE_OBJECT: |
| 380 | + av_log(ctx, AV_LOG_DEBUG, " {\n"); |
| 381 | + for (;;) { |
| 382 | + int size = bytestream_get_be16(&data); |
| 383 | + int t; |
| 384 | + memcpy(buf, data, size); |
| 385 | + buf[size] = 0; |
| 386 | + if (!size) { |
| 387 | + av_log(ctx, AV_LOG_DEBUG, " }\n"); |
| 388 | + data++; |
| 389 | + break; |
| 390 | + } |
| 391 | + if (data + size >= data_end || data + size < data) |
| 392 | + return; |
| 393 | + data += size; |
| 394 | + av_log(ctx, AV_LOG_DEBUG, " %s: ", buf); |
| 395 | + ff_amf_tag_contents(ctx, data, data_end); |
| 396 | + t = ff_amf_tag_size(data, data_end); |
| 397 | + if (t < 0 || data + t >= data_end) |
| 398 | + return; |
| 399 | + data += t; |
| 400 | + } |
| 401 | + return; |
| 402 | + case AMF_DATA_TYPE_OBJECT_END: |
| 403 | + av_log(ctx, AV_LOG_DEBUG, " }\n"); |
| 404 | + return; |
| 405 | + default: |
| 406 | + return; |
| 407 | + } |
| 408 | +} |
| 409 | + |
| 410 | +void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p) |
| 411 | +{ |
| 412 | + av_log(ctx, AV_LOG_DEBUG, "RTMP packet type '%s'(%d) for channel %d, timestamp %d, extra field %d size %d\n", |
| 413 | + rtmp_packet_type(p->type), p->type, p->channel_id, p->timestamp, p->extra, p->data_size); |
| 414 | + if (p->type == RTMP_PT_INVOKE || p->type == RTMP_PT_NOTIFY) { |
| 415 | + uint8_t *src = p->data, *src_end = p->data + p->data_size; |
| 416 | + while (src < src_end) { |
| 417 | + int sz; |
| 418 | + ff_amf_tag_contents(ctx, src, src_end); |
| 419 | + sz = ff_amf_tag_size(src, src_end); |
| 420 | + if (sz < 0) |
| 421 | + break; |
| 422 | + src += sz; |
| 423 | + } |
| 424 | + } else if (p->type == RTMP_PT_SERVER_BW){ |
| 425 | + av_log(ctx, AV_LOG_DEBUG, "Server BW = %d\n", AV_RB32(p->data)); |
| 426 | + } else if (p->type == RTMP_PT_CLIENT_BW){ |
| 427 | + av_log(ctx, AV_LOG_DEBUG, "Client BW = %d\n", AV_RB32(p->data)); |
| 428 | + } else if (p->type != RTMP_PT_AUDIO && p->type != RTMP_PT_VIDEO && p->type != RTMP_PT_METADATA) { |
| 429 | + int i; |
| 430 | + for (i = 0; i < p->data_size; i++) |
| 431 | + av_log(ctx, AV_LOG_DEBUG, " %02X", p->data[i]); |
| 432 | + av_log(ctx, AV_LOG_DEBUG, "\n"); |
| 433 | + } |
| 434 | +} |