annotate ffmpeg/libavformat/rtmppkt.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * RTMP input format
yading@11 3 * Copyright (c) 2009 Kostya Shishkov
yading@11 4 *
yading@11 5 * This file is part of FFmpeg.
yading@11 6 *
yading@11 7 * FFmpeg is free software; you can redistribute it and/or
yading@11 8 * modify it under the terms of the GNU Lesser General Public
yading@11 9 * License as published by the Free Software Foundation; either
yading@11 10 * version 2.1 of the License, or (at your option) any later version.
yading@11 11 *
yading@11 12 * FFmpeg is distributed in the hope that it will be useful,
yading@11 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 15 * Lesser General Public License for more details.
yading@11 16 *
yading@11 17 * You should have received a copy of the GNU Lesser General Public
yading@11 18 * License along with FFmpeg; if not, write to the Free Software
yading@11 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 20 */
yading@11 21
yading@11 22 #include "libavcodec/bytestream.h"
yading@11 23 #include "libavutil/avstring.h"
yading@11 24 #include "libavutil/intfloat.h"
yading@11 25 #include "avformat.h"
yading@11 26
yading@11 27 #include "rtmppkt.h"
yading@11 28 #include "flv.h"
yading@11 29 #include "url.h"
yading@11 30
yading@11 31 void ff_amf_write_bool(uint8_t **dst, int val)
yading@11 32 {
yading@11 33 bytestream_put_byte(dst, AMF_DATA_TYPE_BOOL);
yading@11 34 bytestream_put_byte(dst, val);
yading@11 35 }
yading@11 36
yading@11 37 void ff_amf_write_number(uint8_t **dst, double val)
yading@11 38 {
yading@11 39 bytestream_put_byte(dst, AMF_DATA_TYPE_NUMBER);
yading@11 40 bytestream_put_be64(dst, av_double2int(val));
yading@11 41 }
yading@11 42
yading@11 43 void ff_amf_write_string(uint8_t **dst, const char *str)
yading@11 44 {
yading@11 45 bytestream_put_byte(dst, AMF_DATA_TYPE_STRING);
yading@11 46 bytestream_put_be16(dst, strlen(str));
yading@11 47 bytestream_put_buffer(dst, str, strlen(str));
yading@11 48 }
yading@11 49
yading@11 50 void ff_amf_write_string2(uint8_t **dst, const char *str1, const char *str2)
yading@11 51 {
yading@11 52 int len1 = 0, len2 = 0;
yading@11 53 if (str1)
yading@11 54 len1 = strlen(str1);
yading@11 55 if (str2)
yading@11 56 len2 = strlen(str2);
yading@11 57 bytestream_put_byte(dst, AMF_DATA_TYPE_STRING);
yading@11 58 bytestream_put_be16(dst, len1 + len2);
yading@11 59 bytestream_put_buffer(dst, str1, len1);
yading@11 60 bytestream_put_buffer(dst, str2, len2);
yading@11 61 }
yading@11 62
yading@11 63 void ff_amf_write_null(uint8_t **dst)
yading@11 64 {
yading@11 65 bytestream_put_byte(dst, AMF_DATA_TYPE_NULL);
yading@11 66 }
yading@11 67
yading@11 68 void ff_amf_write_object_start(uint8_t **dst)
yading@11 69 {
yading@11 70 bytestream_put_byte(dst, AMF_DATA_TYPE_OBJECT);
yading@11 71 }
yading@11 72
yading@11 73 void ff_amf_write_field_name(uint8_t **dst, const char *str)
yading@11 74 {
yading@11 75 bytestream_put_be16(dst, strlen(str));
yading@11 76 bytestream_put_buffer(dst, str, strlen(str));
yading@11 77 }
yading@11 78
yading@11 79 void ff_amf_write_object_end(uint8_t **dst)
yading@11 80 {
yading@11 81 /* first two bytes are field name length = 0,
yading@11 82 * AMF object should end with it and end marker
yading@11 83 */
yading@11 84 bytestream_put_be24(dst, AMF_DATA_TYPE_OBJECT_END);
yading@11 85 }
yading@11 86
yading@11 87 int ff_amf_read_bool(GetByteContext *bc, int *val)
yading@11 88 {
yading@11 89 if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_BOOL)
yading@11 90 return AVERROR_INVALIDDATA;
yading@11 91 *val = bytestream2_get_byte(bc);
yading@11 92 return 0;
yading@11 93 }
yading@11 94
yading@11 95 int ff_amf_read_number(GetByteContext *bc, double *val)
yading@11 96 {
yading@11 97 uint64_t read;
yading@11 98 if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_NUMBER)
yading@11 99 return AVERROR_INVALIDDATA;
yading@11 100 read = bytestream2_get_be64(bc);
yading@11 101 *val = av_int2double(read);
yading@11 102 return 0;
yading@11 103 }
yading@11 104
yading@11 105 int ff_amf_read_string(GetByteContext *bc, uint8_t *str,
yading@11 106 int strsize, int *length)
yading@11 107 {
yading@11 108 int stringlen = 0;
yading@11 109 int readsize;
yading@11 110 if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_STRING)
yading@11 111 return AVERROR_INVALIDDATA;
yading@11 112 stringlen = bytestream2_get_be16(bc);
yading@11 113 if (stringlen + 1 > strsize)
yading@11 114 return AVERROR(EINVAL);
yading@11 115 readsize = bytestream2_get_buffer(bc, str, stringlen);
yading@11 116 if (readsize != stringlen) {
yading@11 117 av_log(NULL, AV_LOG_WARNING,
yading@11 118 "Unable to read as many bytes as AMF string signaled\n");
yading@11 119 }
yading@11 120 str[readsize] = '\0';
yading@11 121 *length = FFMIN(stringlen, readsize);
yading@11 122 return 0;
yading@11 123 }
yading@11 124
yading@11 125 int ff_amf_read_null(GetByteContext *bc)
yading@11 126 {
yading@11 127 if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_NULL)
yading@11 128 return AVERROR_INVALIDDATA;
yading@11 129 return 0;
yading@11 130 }
yading@11 131
yading@11 132 int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
yading@11 133 int chunk_size, RTMPPacket *prev_pkt)
yading@11 134 {
yading@11 135 uint8_t hdr;
yading@11 136
yading@11 137 if (ffurl_read(h, &hdr, 1) != 1)
yading@11 138 return AVERROR(EIO);
yading@11 139
yading@11 140 return ff_rtmp_packet_read_internal(h, p, chunk_size, prev_pkt, hdr);
yading@11 141 }
yading@11 142
yading@11 143 int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size,
yading@11 144 RTMPPacket *prev_pkt, uint8_t hdr)
yading@11 145 {
yading@11 146
yading@11 147 uint8_t t, buf[16];
yading@11 148 int channel_id, timestamp, data_size, offset = 0;
yading@11 149 uint32_t extra = 0;
yading@11 150 enum RTMPPacketType type;
yading@11 151 int size = 0;
yading@11 152 int ret;
yading@11 153
yading@11 154 size++;
yading@11 155 channel_id = hdr & 0x3F;
yading@11 156
yading@11 157 if (channel_id < 2) { //special case for channel number >= 64
yading@11 158 buf[1] = 0;
yading@11 159 if (ffurl_read_complete(h, buf, channel_id + 1) != channel_id + 1)
yading@11 160 return AVERROR(EIO);
yading@11 161 size += channel_id + 1;
yading@11 162 channel_id = AV_RL16(buf) + 64;
yading@11 163 }
yading@11 164 data_size = prev_pkt[channel_id].data_size;
yading@11 165 type = prev_pkt[channel_id].type;
yading@11 166 extra = prev_pkt[channel_id].extra;
yading@11 167
yading@11 168 hdr >>= 6;
yading@11 169 if (hdr == RTMP_PS_ONEBYTE) {
yading@11 170 timestamp = prev_pkt[channel_id].ts_delta;
yading@11 171 } else {
yading@11 172 if (ffurl_read_complete(h, buf, 3) != 3)
yading@11 173 return AVERROR(EIO);
yading@11 174 size += 3;
yading@11 175 timestamp = AV_RB24(buf);
yading@11 176 if (hdr != RTMP_PS_FOURBYTES) {
yading@11 177 if (ffurl_read_complete(h, buf, 3) != 3)
yading@11 178 return AVERROR(EIO);
yading@11 179 size += 3;
yading@11 180 data_size = AV_RB24(buf);
yading@11 181 if (ffurl_read_complete(h, buf, 1) != 1)
yading@11 182 return AVERROR(EIO);
yading@11 183 size++;
yading@11 184 type = buf[0];
yading@11 185 if (hdr == RTMP_PS_TWELVEBYTES) {
yading@11 186 if (ffurl_read_complete(h, buf, 4) != 4)
yading@11 187 return AVERROR(EIO);
yading@11 188 size += 4;
yading@11 189 extra = AV_RL32(buf);
yading@11 190 }
yading@11 191 }
yading@11 192 if (timestamp == 0xFFFFFF) {
yading@11 193 if (ffurl_read_complete(h, buf, 4) != 4)
yading@11 194 return AVERROR(EIO);
yading@11 195 timestamp = AV_RB32(buf);
yading@11 196 }
yading@11 197 }
yading@11 198 if (hdr != RTMP_PS_TWELVEBYTES)
yading@11 199 timestamp += prev_pkt[channel_id].timestamp;
yading@11 200
yading@11 201 if ((ret = ff_rtmp_packet_create(p, channel_id, type, timestamp,
yading@11 202 data_size)) < 0)
yading@11 203 return ret;
yading@11 204 p->extra = extra;
yading@11 205 // save history
yading@11 206 prev_pkt[channel_id].channel_id = channel_id;
yading@11 207 prev_pkt[channel_id].type = type;
yading@11 208 prev_pkt[channel_id].data_size = data_size;
yading@11 209 prev_pkt[channel_id].ts_delta = timestamp - prev_pkt[channel_id].timestamp;
yading@11 210 prev_pkt[channel_id].timestamp = timestamp;
yading@11 211 prev_pkt[channel_id].extra = extra;
yading@11 212 while (data_size > 0) {
yading@11 213 int toread = FFMIN(data_size, chunk_size);
yading@11 214 if (ffurl_read_complete(h, p->data + offset, toread) != toread) {
yading@11 215 ff_rtmp_packet_destroy(p);
yading@11 216 return AVERROR(EIO);
yading@11 217 }
yading@11 218 data_size -= chunk_size;
yading@11 219 offset += chunk_size;
yading@11 220 size += chunk_size;
yading@11 221 if (data_size > 0) {
yading@11 222 if ((ret = ffurl_read_complete(h, &t, 1)) < 0) { // marker
yading@11 223 ff_rtmp_packet_destroy(p);
yading@11 224 return ret;
yading@11 225 }
yading@11 226 size++;
yading@11 227 if (t != (0xC0 + channel_id))
yading@11 228 return -1;
yading@11 229 }
yading@11 230 }
yading@11 231 return size;
yading@11 232 }
yading@11 233
yading@11 234 int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt,
yading@11 235 int chunk_size, RTMPPacket *prev_pkt)
yading@11 236 {
yading@11 237 uint8_t pkt_hdr[16], *p = pkt_hdr;
yading@11 238 int mode = RTMP_PS_TWELVEBYTES;
yading@11 239 int off = 0;
yading@11 240 int size = 0;
yading@11 241 int ret;
yading@11 242
yading@11 243 pkt->ts_delta = pkt->timestamp - prev_pkt[pkt->channel_id].timestamp;
yading@11 244
yading@11 245 //if channel_id = 0, this is first presentation of prev_pkt, send full hdr.
yading@11 246 if (prev_pkt[pkt->channel_id].channel_id &&
yading@11 247 pkt->extra == prev_pkt[pkt->channel_id].extra) {
yading@11 248 if (pkt->type == prev_pkt[pkt->channel_id].type &&
yading@11 249 pkt->data_size == prev_pkt[pkt->channel_id].data_size) {
yading@11 250 mode = RTMP_PS_FOURBYTES;
yading@11 251 if (pkt->ts_delta == prev_pkt[pkt->channel_id].ts_delta)
yading@11 252 mode = RTMP_PS_ONEBYTE;
yading@11 253 } else {
yading@11 254 mode = RTMP_PS_EIGHTBYTES;
yading@11 255 }
yading@11 256 }
yading@11 257
yading@11 258 if (pkt->channel_id < 64) {
yading@11 259 bytestream_put_byte(&p, pkt->channel_id | (mode << 6));
yading@11 260 } else if (pkt->channel_id < 64 + 256) {
yading@11 261 bytestream_put_byte(&p, 0 | (mode << 6));
yading@11 262 bytestream_put_byte(&p, pkt->channel_id - 64);
yading@11 263 } else {
yading@11 264 bytestream_put_byte(&p, 1 | (mode << 6));
yading@11 265 bytestream_put_le16(&p, pkt->channel_id - 64);
yading@11 266 }
yading@11 267 if (mode != RTMP_PS_ONEBYTE) {
yading@11 268 uint32_t timestamp = pkt->timestamp;
yading@11 269 if (mode != RTMP_PS_TWELVEBYTES)
yading@11 270 timestamp = pkt->ts_delta;
yading@11 271 bytestream_put_be24(&p, timestamp >= 0xFFFFFF ? 0xFFFFFF : timestamp);
yading@11 272 if (mode != RTMP_PS_FOURBYTES) {
yading@11 273 bytestream_put_be24(&p, pkt->data_size);
yading@11 274 bytestream_put_byte(&p, pkt->type);
yading@11 275 if (mode == RTMP_PS_TWELVEBYTES)
yading@11 276 bytestream_put_le32(&p, pkt->extra);
yading@11 277 }
yading@11 278 if (timestamp >= 0xFFFFFF)
yading@11 279 bytestream_put_be32(&p, timestamp);
yading@11 280 }
yading@11 281 // save history
yading@11 282 prev_pkt[pkt->channel_id].channel_id = pkt->channel_id;
yading@11 283 prev_pkt[pkt->channel_id].type = pkt->type;
yading@11 284 prev_pkt[pkt->channel_id].data_size = pkt->data_size;
yading@11 285 prev_pkt[pkt->channel_id].timestamp = pkt->timestamp;
yading@11 286 if (mode != RTMP_PS_TWELVEBYTES) {
yading@11 287 prev_pkt[pkt->channel_id].ts_delta = pkt->ts_delta;
yading@11 288 } else {
yading@11 289 prev_pkt[pkt->channel_id].ts_delta = pkt->timestamp;
yading@11 290 }
yading@11 291 prev_pkt[pkt->channel_id].extra = pkt->extra;
yading@11 292
yading@11 293 if ((ret = ffurl_write(h, pkt_hdr, p - pkt_hdr)) < 0)
yading@11 294 return ret;
yading@11 295 size = p - pkt_hdr + pkt->data_size;
yading@11 296 while (off < pkt->data_size) {
yading@11 297 int towrite = FFMIN(chunk_size, pkt->data_size - off);
yading@11 298 if ((ret = ffurl_write(h, pkt->data + off, towrite)) < 0)
yading@11 299 return ret;
yading@11 300 off += towrite;
yading@11 301 if (off < pkt->data_size) {
yading@11 302 uint8_t marker = 0xC0 | pkt->channel_id;
yading@11 303 if ((ret = ffurl_write(h, &marker, 1)) < 0)
yading@11 304 return ret;
yading@11 305 size++;
yading@11 306 }
yading@11 307 }
yading@11 308 return size;
yading@11 309 }
yading@11 310
yading@11 311 int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type,
yading@11 312 int timestamp, int size)
yading@11 313 {
yading@11 314 if (size) {
yading@11 315 pkt->data = av_malloc(size);
yading@11 316 if (!pkt->data)
yading@11 317 return AVERROR(ENOMEM);
yading@11 318 }
yading@11 319 pkt->data_size = size;
yading@11 320 pkt->channel_id = channel_id;
yading@11 321 pkt->type = type;
yading@11 322 pkt->timestamp = timestamp;
yading@11 323 pkt->extra = 0;
yading@11 324 pkt->ts_delta = 0;
yading@11 325
yading@11 326 return 0;
yading@11 327 }
yading@11 328
yading@11 329 void ff_rtmp_packet_destroy(RTMPPacket *pkt)
yading@11 330 {
yading@11 331 if (!pkt)
yading@11 332 return;
yading@11 333 av_freep(&pkt->data);
yading@11 334 pkt->data_size = 0;
yading@11 335 }
yading@11 336
yading@11 337 int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
yading@11 338 {
yading@11 339 const uint8_t *base = data;
yading@11 340
yading@11 341 if (data >= data_end)
yading@11 342 return -1;
yading@11 343 switch (*data++) {
yading@11 344 case AMF_DATA_TYPE_NUMBER: return 9;
yading@11 345 case AMF_DATA_TYPE_BOOL: return 2;
yading@11 346 case AMF_DATA_TYPE_STRING: return 3 + AV_RB16(data);
yading@11 347 case AMF_DATA_TYPE_LONG_STRING: return 5 + AV_RB32(data);
yading@11 348 case AMF_DATA_TYPE_NULL: return 1;
yading@11 349 case AMF_DATA_TYPE_ARRAY:
yading@11 350 data += 4;
yading@11 351 case AMF_DATA_TYPE_OBJECT:
yading@11 352 for (;;) {
yading@11 353 int size = bytestream_get_be16(&data);
yading@11 354 int t;
yading@11 355 if (!size) {
yading@11 356 data++;
yading@11 357 break;
yading@11 358 }
yading@11 359 if (size < 0 || size >= data_end - data)
yading@11 360 return -1;
yading@11 361 data += size;
yading@11 362 t = ff_amf_tag_size(data, data_end);
yading@11 363 if (t < 0 || t >= data_end - data)
yading@11 364 return -1;
yading@11 365 data += t;
yading@11 366 }
yading@11 367 return data - base;
yading@11 368 case AMF_DATA_TYPE_OBJECT_END: return 1;
yading@11 369 default: return -1;
yading@11 370 }
yading@11 371 }
yading@11 372
yading@11 373 int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end,
yading@11 374 const uint8_t *name, uint8_t *dst, int dst_size)
yading@11 375 {
yading@11 376 int namelen = strlen(name);
yading@11 377 int len;
yading@11 378
yading@11 379 while (*data != AMF_DATA_TYPE_OBJECT && data < data_end) {
yading@11 380 len = ff_amf_tag_size(data, data_end);
yading@11 381 if (len < 0)
yading@11 382 len = data_end - data;
yading@11 383 data += len;
yading@11 384 }
yading@11 385 if (data_end - data < 3)
yading@11 386 return -1;
yading@11 387 data++;
yading@11 388 for (;;) {
yading@11 389 int size = bytestream_get_be16(&data);
yading@11 390 if (!size)
yading@11 391 break;
yading@11 392 if (size < 0 || size >= data_end - data)
yading@11 393 return -1;
yading@11 394 data += size;
yading@11 395 if (size == namelen && !memcmp(data-size, name, namelen)) {
yading@11 396 switch (*data++) {
yading@11 397 case AMF_DATA_TYPE_NUMBER:
yading@11 398 snprintf(dst, dst_size, "%g", av_int2double(AV_RB64(data)));
yading@11 399 break;
yading@11 400 case AMF_DATA_TYPE_BOOL:
yading@11 401 snprintf(dst, dst_size, "%s", *data ? "true" : "false");
yading@11 402 break;
yading@11 403 case AMF_DATA_TYPE_STRING:
yading@11 404 len = bytestream_get_be16(&data);
yading@11 405 av_strlcpy(dst, data, FFMIN(len+1, dst_size));
yading@11 406 break;
yading@11 407 default:
yading@11 408 return -1;
yading@11 409 }
yading@11 410 return 0;
yading@11 411 }
yading@11 412 len = ff_amf_tag_size(data, data_end);
yading@11 413 if (len < 0 || len >= data_end - data)
yading@11 414 return -1;
yading@11 415 data += len;
yading@11 416 }
yading@11 417 return -1;
yading@11 418 }
yading@11 419
yading@11 420 static const char* rtmp_packet_type(int type)
yading@11 421 {
yading@11 422 switch (type) {
yading@11 423 case RTMP_PT_CHUNK_SIZE: return "chunk size";
yading@11 424 case RTMP_PT_BYTES_READ: return "bytes read";
yading@11 425 case RTMP_PT_PING: return "ping";
yading@11 426 case RTMP_PT_SERVER_BW: return "server bandwidth";
yading@11 427 case RTMP_PT_CLIENT_BW: return "client bandwidth";
yading@11 428 case RTMP_PT_AUDIO: return "audio packet";
yading@11 429 case RTMP_PT_VIDEO: return "video packet";
yading@11 430 case RTMP_PT_FLEX_STREAM: return "Flex shared stream";
yading@11 431 case RTMP_PT_FLEX_OBJECT: return "Flex shared object";
yading@11 432 case RTMP_PT_FLEX_MESSAGE: return "Flex shared message";
yading@11 433 case RTMP_PT_NOTIFY: return "notification";
yading@11 434 case RTMP_PT_SHARED_OBJ: return "shared object";
yading@11 435 case RTMP_PT_INVOKE: return "invoke";
yading@11 436 case RTMP_PT_METADATA: return "metadata";
yading@11 437 default: return "unknown";
yading@11 438 }
yading@11 439 }
yading@11 440
yading@11 441 static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end)
yading@11 442 {
yading@11 443 unsigned int size;
yading@11 444 char buf[1024];
yading@11 445
yading@11 446 if (data >= data_end)
yading@11 447 return;
yading@11 448 switch (*data++) {
yading@11 449 case AMF_DATA_TYPE_NUMBER:
yading@11 450 av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2double(AV_RB64(data)));
yading@11 451 return;
yading@11 452 case AMF_DATA_TYPE_BOOL:
yading@11 453 av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data);
yading@11 454 return;
yading@11 455 case AMF_DATA_TYPE_STRING:
yading@11 456 case AMF_DATA_TYPE_LONG_STRING:
yading@11 457 if (data[-1] == AMF_DATA_TYPE_STRING) {
yading@11 458 size = bytestream_get_be16(&data);
yading@11 459 } else {
yading@11 460 size = bytestream_get_be32(&data);
yading@11 461 }
yading@11 462 size = FFMIN(size, sizeof(buf) - 1);
yading@11 463 memcpy(buf, data, size);
yading@11 464 buf[size] = 0;
yading@11 465 av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf);
yading@11 466 return;
yading@11 467 case AMF_DATA_TYPE_NULL:
yading@11 468 av_log(ctx, AV_LOG_DEBUG, " NULL\n");
yading@11 469 return;
yading@11 470 case AMF_DATA_TYPE_ARRAY:
yading@11 471 data += 4;
yading@11 472 case AMF_DATA_TYPE_OBJECT:
yading@11 473 av_log(ctx, AV_LOG_DEBUG, " {\n");
yading@11 474 for (;;) {
yading@11 475 int t;
yading@11 476 size = bytestream_get_be16(&data);
yading@11 477 av_strlcpy(buf, data, FFMIN(sizeof(buf), size + 1));
yading@11 478 if (!size) {
yading@11 479 av_log(ctx, AV_LOG_DEBUG, " }\n");
yading@11 480 data++;
yading@11 481 break;
yading@11 482 }
yading@11 483 if (size >= data_end - data)
yading@11 484 return;
yading@11 485 data += size;
yading@11 486 av_log(ctx, AV_LOG_DEBUG, " %s: ", buf);
yading@11 487 ff_amf_tag_contents(ctx, data, data_end);
yading@11 488 t = ff_amf_tag_size(data, data_end);
yading@11 489 if (t < 0 || t >= data_end - data)
yading@11 490 return;
yading@11 491 data += t;
yading@11 492 }
yading@11 493 return;
yading@11 494 case AMF_DATA_TYPE_OBJECT_END:
yading@11 495 av_log(ctx, AV_LOG_DEBUG, " }\n");
yading@11 496 return;
yading@11 497 default:
yading@11 498 return;
yading@11 499 }
yading@11 500 }
yading@11 501
yading@11 502 void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
yading@11 503 {
yading@11 504 av_log(ctx, AV_LOG_DEBUG, "RTMP packet type '%s'(%d) for channel %d, timestamp %d, extra field %d size %d\n",
yading@11 505 rtmp_packet_type(p->type), p->type, p->channel_id, p->timestamp, p->extra, p->data_size);
yading@11 506 if (p->type == RTMP_PT_INVOKE || p->type == RTMP_PT_NOTIFY) {
yading@11 507 uint8_t *src = p->data, *src_end = p->data + p->data_size;
yading@11 508 while (src < src_end) {
yading@11 509 int sz;
yading@11 510 ff_amf_tag_contents(ctx, src, src_end);
yading@11 511 sz = ff_amf_tag_size(src, src_end);
yading@11 512 if (sz < 0)
yading@11 513 break;
yading@11 514 src += sz;
yading@11 515 }
yading@11 516 } else if (p->type == RTMP_PT_SERVER_BW){
yading@11 517 av_log(ctx, AV_LOG_DEBUG, "Server BW = %d\n", AV_RB32(p->data));
yading@11 518 } else if (p->type == RTMP_PT_CLIENT_BW){
yading@11 519 av_log(ctx, AV_LOG_DEBUG, "Client BW = %d\n", AV_RB32(p->data));
yading@11 520 } else if (p->type != RTMP_PT_AUDIO && p->type != RTMP_PT_VIDEO && p->type != RTMP_PT_METADATA) {
yading@11 521 int i;
yading@11 522 for (i = 0; i < p->data_size; i++)
yading@11 523 av_log(ctx, AV_LOG_DEBUG, " %02X", p->data[i]);
yading@11 524 av_log(ctx, AV_LOG_DEBUG, "\n");
yading@11 525 }
yading@11 526 }