1 /*
2 * RTMP input format
3 * Copyright (c) 2009 Konstantin Shishkov
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
26
30
32 {
34 bytestream_put_byte(dst,
val);
35 }
36
38 {
41 }
42
44 {
46 bytestream_put_be16(dst, strlen(
str));
48 }
49
51 {
52 int len1 = 0, len2 = 0;
53 if (str1)
54 len1 = strlen(str1);
55 if (str2)
56 len2 = strlen(str2);
58 bytestream_put_be16(dst, len1 + len2);
61 }
62
64 {
66 }
67
69 {
71 }
72
74 {
75 bytestream_put_be16(dst, strlen(
str));
77 }
78
80 {
81 /* first two bytes are field name length = 0,
82 * AMF object should end with it and end marker
83 */
85 }
86
88 {
89 uint64_t read;
92 read = bytestream2_get_be64(bc);
94 return 0;
95 }
96
98 int strsize, int *length)
99 {
100 int stringlen = 0;
101 int readsize;
102 stringlen = bytestream2_get_be16(bc);
103 if (stringlen + 1 > strsize)
106 if (readsize != stringlen) {
108 "Unable to read as many bytes as AMF string signaled\n");
109 }
110 str[readsize] =
'0円';
111 *length =
FFMIN(stringlen, readsize);
112 return 0;
113 }
114
116 int strsize, int *length)
117 {
121 }
122
124 {
127 return 0;
128 }
129
132 {
133 int nb_alloc;
136 return 0;
137
139 // This can't use the av_reallocp family of functions, since we
140 // would need to free each element in the array before the array
141 // itself is freed.
143 if (!ptr)
145 memset(ptr + *nb_prev_pkt, 0, (nb_alloc - *nb_prev_pkt) * sizeof(*ptr));
146 *prev_pkt = ptr;
147 *nb_prev_pkt = nb_alloc;
148 return 0;
149 }
150
152 int chunk_size,
RTMPPacket **prev_pkt,
int *nb_prev_pkt)
153 {
154 uint8_t hdr;
155
158
160 nb_prev_pkt, hdr);
161 }
162
165 int *nb_prev_pkt, uint8_t hdr)
166 {
167
168 uint8_t buf[16];
169 int channel_id, timestamp,
size;
170 uint32_t ts_field; // non-extended timestamp or delta field
171 uint32_t extra = 0;
173 int written = 0;
176
177 written++;
178 channel_id = hdr & 0x3F;
179
180 if (channel_id < 2) { //special case for channel number >= 64
181 buf[1] = 0;
184 written += channel_id + 1;
185 channel_id =
AV_RL16(buf) + 64;
186 }
188 channel_id)) < 0)
190 prev_pkt = *prev_pkt_ptr;
193 extra = prev_pkt[channel_id].
extra;
194
195 hdr >>= 6; // header size indicator
197 ts_field = prev_pkt[channel_id].
ts_field;
198 } else {
201 written += 3;
206 written += 3;
210 written++;
215 written += 4;
217 }
218 }
219 }
220 if (ts_field == 0xFFFFFF) {
224 } else {
225 timestamp = ts_field;
226 }
228 timestamp += prev_pkt[channel_id].
timestamp;
229
230 if (prev_pkt[channel_id].read &&
size != prev_pkt[channel_id].
size) {
234 prev_pkt[channel_id].
read = 0;
236 }
237
238 if (!prev_pkt[channel_id].read) {
244 prev_pkt[channel_id].
ts_field = ts_field;
245 prev_pkt[channel_id].
timestamp = timestamp;
246 } else {
247 // previous packet in this channel hasn't completed reading
259 }
261 // save history
265 prev_pkt[channel_id].
extra = extra;
267
272 }
276
284 }
285
286 prev_pkt[channel_id].
read = 0;
// read complete; reset if needed
288 }
289
292 uint8_t hdr)
293 {
294 while (1) {
296 nb_prev_pkt, hdr);
299
302 }
303 }
304
307 int *nb_prev_pkt)
308 {
309 uint8_t pkt_hdr[16], *p = pkt_hdr;
311 int off = 0;
312 int written = 0;
315 int use_delta; // flag if using timestamp delta, not RTMP_PS_TWELVEBYTES
316 uint32_t timestamp; // full 32-bit timestamp or delta value
317
319 pkt->channel_id)) < 0)
321 prev_pkt = *prev_pkt_ptr;
322
323 //if channel_id = 0, this is first presentation of prev_pkt, send full hdr.
327
328 timestamp =
pkt->timestamp;
329 if (use_delta) {
331 }
332 if (timestamp >= 0xFFFFFF) {
333 pkt->ts_field = 0xFFFFFF;
334 } else {
335 pkt->ts_field = timestamp;
336 }
337
338 if (use_delta) {
339 if (
pkt->type == prev_pkt[
pkt->channel_id].
type &&
344 } else {
346 }
347 }
348
349 if (
pkt->channel_id < 64) {
350 bytestream_put_byte(&p,
pkt->channel_id | (
mode << 6));
351 }
else if (
pkt->channel_id < 64 + 256) {
352 bytestream_put_byte(&p, 0 | (
mode << 6));
353 bytestream_put_byte(&p,
pkt->channel_id - 64);
354 } else {
355 bytestream_put_byte(&p, 1 | (
mode << 6));
356 bytestream_put_le16(&p,
pkt->channel_id - 64);
357 }
359 bytestream_put_be24(&p,
pkt->ts_field);
361 bytestream_put_be24(&p,
pkt->
size);
362 bytestream_put_byte(&p,
pkt->type);
364 bytestream_put_le32(&p,
pkt->extra);
365 }
366 }
367 if (
pkt->ts_field == 0xFFFFFF)
368 bytestream_put_be32(&p, timestamp);
369 // save history
376
377 // FIXME:
378 // Writing packets is currently not optimized to minimize system calls.
379 // Since system calls flush on exit which we cannot change in a system-independant way.
380 // We should fix this behavior and by writing packets in a single or in as few as possible system calls.
381 // Protocols like TCP and RTMP should benefit from this when enabling TCP_NODELAY.
382
385 written = p - pkt_hdr +
pkt->
size;
386 while (off < pkt->
size) {
390 off += towrite;
391 if (off < pkt->
size) {
392 uint8_t marker = 0xC0 |
pkt->channel_id;
395 written++;
396 if (
pkt->ts_field == 0xFFFFFF) {
397 uint8_t ts_header[4];
401 written += 4;
402 }
403 }
404 }
405 return written;
406 }
407
409 int timestamp,
int size)
410 {
415 }
417 pkt->channel_id = channel_id;
419 pkt->timestamp = timestamp;
422
423 return 0;
424 }
425
427 {
429 return;
432 }
433
435 {
437 unsigned nb = -1;
439
441 return -1;
442
443 type = bytestream2_get_byte(gb);
446 bytestream2_get_be64(gb);
447 return 0;
449 bytestream2_get_byte(gb);
450 return 0;
453 return 0;
456 return 0;
458 return 0;
461 return 0;
465 nb = bytestream2_get_be32(gb);
468 int t;
470 int size = bytestream2_get_be16(gb);
472 bytestream2_get_byte(gb);
473 break;
474 }
476 return -1;
478 }
481 return -1;
482 }
483 return 0;
485 default: return -1;
486 }
487 }
488
490 {
493
494 if (
data >= data_end)
495 return -1;
496
498
501 return -1;
504 }
505
507 const uint8_t *
name, uint8_t *dst,
int dst_size)
508 {
509 int namelen = strlen(
name);
511
515 return -1;
516 }
518 return -1;
519 bytestream2_get_byte(gb);
520
521 for (;;) {
522 int size = bytestream2_get_be16(gb);
524 break;
526 return -1;
529 switch (bytestream2_get_byte(gb)) {
532 break;
534 snprintf(dst, dst_size,
"%s", bytestream2_get_byte(gb) ?
"true" :
"false");
535 break;
537 len = bytestream2_get_be16(gb);
538 if (dst_size < 1)
539 return -1;
540 if (dst_size <
len + 1)
544 break;
545 default:
546 return -1;
547 }
548 return 0;
549 }
552 return -1;
553 }
554 return -1;
555 }
556
558 const uint8_t *
name, uint8_t *dst,
int dst_size)
559 {
561
562 if (
data >= data_end)
563 return -1;
564
566
568 }
569
570 #ifdef DEBUG
571 static const char* rtmp_packet_type(
int type)
572 {
588 default: return "unknown";
589 }
590 }
591
592 static void amf_tag_contents(
void *
ctx,
const uint8_t *
data,
593 const uint8_t *data_end)
594 {
595 unsigned int size, nb = -1;
596 char buf[1024];
599
600 if (
data >= data_end)
601 return;
605 return;
608 return;
613 } else {
615 }
620 return;
623 return;
627 nb = bytestream_get_be32(&
data);
631 int t;
638 break;
639 }
643 return;
646 }
647 amf_tag_contents(
ctx,
data, data_end);
649 if (t < 0 || t >= data_end -
data)
650 return;
652 }
653 return;
656 return;
657 default:
658 return;
659 }
660 }
661
663 {
664 av_log(
ctx,
AV_LOG_DEBUG,
"RTMP packet type '%s'(%d) for channel %d, timestamp %d, extra field %d size %d\n",
668 while (
src < src_end) {
669 int sz;
670 amf_tag_contents(
ctx,
src, src_end);
672 if (sz < 0)
673 break;
675 }
685 }
686 }
687 #endif
688
690 {
693
695 return 0;
696
698
701 return 0;
702
704 if ((
size -= 4 + 1) < 0)
705 return 0;
706 amf_len = bytestream_get_be32(&
data);
707 } else {
708 if ((
size -= 2 + 1) < 0)
709 return 0;
710 amf_len = bytestream_get_be16(&
data);
711 }
712
714 return 0;
715
717 return 0;
718
720 }