1 /*
2 * RTMP input format
3 * Copyright (c) 2009 Kostya 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 {
91 *val = bytestream2_get_byte(bc);
92 return 0;
93 }
94
96 {
97 uint64_t read;
100 read = bytestream2_get_be64(bc);
102 return 0;
103 }
104
106 int strsize, int *length)
107 {
108 int stringlen = 0;
109 int readsize;
112 stringlen = bytestream2_get_be16(bc);
113 if (stringlen + 1 > strsize)
116 if (readsize != stringlen) {
118 "Unable to read as many bytes as AMF string signaled\n");
119 }
120 str[readsize] = '0円';
121 *length =
FFMIN(stringlen, readsize);
122 return 0;
123 }
124
126 {
129 return 0;
130 }
131
134 {
136
139
141 }
142
145 {
146
148 int channel_id, timestamp, data_size,
offset = 0;
149 uint32_t extra = 0;
152 int ret;
153
154 size++;
155 channel_id = hdr & 0x3F;
156
157 if (channel_id < 2) { //special case for channel number >= 64
158 buf[1] = 0;
161 size += channel_id + 1;
162 channel_id =
AV_RL16(buf) + 64;
163 }
164 data_size = prev_pkt[channel_id].
data_size;
165 type = prev_pkt[channel_id].
type;
166 extra = prev_pkt[channel_id].
extra;
167
168 hdr >>= 6;
170 timestamp = prev_pkt[channel_id].
ts_delta;
171 } else {
174 size += 3;
179 size += 3;
183 size++;
184 type = buf[0];
188 size += 4;
190 }
191 }
192 if (timestamp == 0xFFFFFF) {
196 }
197 }
199 timestamp += prev_pkt[channel_id].
timestamp;
200
202 data_size)) < 0)
203 return ret;
205 // save history
207 prev_pkt[channel_id].
type = type;
208 prev_pkt[channel_id].
data_size = data_size;
210 prev_pkt[channel_id].
timestamp = timestamp;
211 prev_pkt[channel_id].
extra = extra;
212 while (data_size > 0) {
213 int toread =
FFMIN(data_size, chunk_size);
217 }
218 data_size -= chunk_size;
219 offset += chunk_size;
220 size += chunk_size;
221 if (data_size > 0) {
224 return ret;
225 }
226 size++;
227 if (t != (0xC0 + channel_id))
228 return -1;
229 }
230 }
232 }
233
236 {
237 uint8_t pkt_hdr[16], *p = pkt_hdr;
241 int ret;
242
244
245 //if channel_id = 0, this is first presentation of prev_pkt, send full hdr.
253 } else {
255 }
256 }
257
259 bytestream_put_byte(&p, pkt->
channel_id | (mode << 6));
261 bytestream_put_byte(&p, 0 | (mode << 6));
262 bytestream_put_byte(&p, pkt->
channel_id - 64);
263 } else {
264 bytestream_put_byte(&p, 1 | (mode << 6));
265 bytestream_put_le16(&p, pkt->
channel_id - 64);
266 }
271 bytestream_put_be24(&p, timestamp >= 0xFFFFFF ? 0xFFFFFF : timestamp);
274 bytestream_put_byte(&p, pkt->
type);
276 bytestream_put_le32(&p, pkt->
extra);
277 }
278 if (timestamp >= 0xFFFFFF)
279 bytestream_put_be32(&p, timestamp);
280 }
281 // save history
288 } else {
290 }
292
293 if ((ret =
ffurl_write(h, pkt_hdr, p - pkt_hdr)) < 0)
294 return ret;
296 while (off < pkt->data_size) {
299 return ret;
300 off += towrite;
301 if (off < pkt->data_size) {
304 return ret;
305 size++;
306 }
307 }
309 }
310
312 int timestamp,
int size)
313 {
314 if (size) {
318 }
325
326 return 0;
327 }
328
330 {
331 if (!pkt)
332 return;
335 }
336
338 {
340
341 if (data >= data_end)
342 return -1;
343 switch (*data++) {
350 data += 4;
352 for (;;) {
353 int size = bytestream_get_be16(&data);
355 if (!size) {
356 data++;
357 break;
358 }
359 if (size < 0 || size >= data_end - data)
360 return -1;
363 if (t < 0 || t >= data_end - data)
364 return -1;
366 }
367 return data - base;
369 default: return -1;
370 }
371 }
372
375 {
376 int namelen = strlen(name);
378
381 if (len < 0)
382 len = data_end -
data;
384 }
385 if (data_end - data < 3)
386 return -1;
387 data++;
388 for (;;) {
389 int size = bytestream_get_be16(&data);
390 if (!size)
391 break;
392 if (size < 0 || size >= data_end - data)
393 return -1;
395 if (size == namelen && !memcmp(data-size, name, namelen)) {
396 switch (*data++) {
399 break;
401 snprintf(dst, dst_size,
"%s", *data ?
"true" :
"false");
402 break;
404 len = bytestream_get_be16(&data);
406 break;
407 default:
408 return -1;
409 }
410 return 0;
411 }
413 if (len < 0 || len >= data_end - data)
414 return -1;
416 }
417 return -1;
418 }
419
421 {
422 switch (type) {
437 default: return "unknown";
438 }
439 }
440
442 {
444 char buf[1024];
445
446 if (data >= data_end)
447 return;
448 switch (*data++) {
451 return;
454 return;
458 size = bytestream_get_be16(&data);
459 } else {
460 size = bytestream_get_be32(&data);
461 }
462 size =
FFMIN(size,
sizeof(buf) - 1);
463 memcpy(buf, data, size);
466 return;
469 return;
471 data += 4;
474 for (;;) {
476 size = bytestream_get_be16(&data);
478 if (!size) {
480 data++;
481 break;
482 }
483 if (size >= data_end - data)
484 return;
489 if (t < 0 || t >= data_end - data)
490 return;
492 }
493 return;
496 return;
497 default:
498 return;
499 }
500 }
501
503 {
504 av_log(ctx,
AV_LOG_DEBUG,
"RTMP packet type '%s'(%d) for channel %d, timestamp %d, extra field %d size %d\n",
508 while (src < src_end) {
509 int sz;
512 if (sz < 0)
513 break;
514 src += sz;
515 }
521 int i;
525 }
526 }