1/*
2 * RTMP input format
3 * Copyright (c) 2009 Kostya Shishkov
4 *
5 * This file is part of Libav.
6 *
7 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "libavcodec/bytestream.h"
23#include "libavutil/avstring.h"
24#include "libavutil/intfloat.h"
25#include "avformat.h"
26
27#include "rtmppkt.h"
28#include "flv.h"
29#include "url.h"
30
31void ff_amf_write_bool(uint8_t **dst, int val)
32{
33    bytestream_put_byte(dst, AMF_DATA_TYPE_BOOL);
34    bytestream_put_byte(dst, val);
35}
36
37void ff_amf_write_number(uint8_t **dst, double val)
38{
39    bytestream_put_byte(dst, AMF_DATA_TYPE_NUMBER);
40    bytestream_put_be64(dst, av_double2int(val));
41}
42
43void ff_amf_write_string(uint8_t **dst, const char *str)
44{
45    bytestream_put_byte(dst, AMF_DATA_TYPE_STRING);
46    bytestream_put_be16(dst, strlen(str));
47    bytestream_put_buffer(dst, str, strlen(str));
48}
49
50void ff_amf_write_null(uint8_t **dst)
51{
52    bytestream_put_byte(dst, AMF_DATA_TYPE_NULL);
53}
54
55void ff_amf_write_object_start(uint8_t **dst)
56{
57    bytestream_put_byte(dst, AMF_DATA_TYPE_OBJECT);
58}
59
60void ff_amf_write_field_name(uint8_t **dst, const char *str)
61{
62    bytestream_put_be16(dst, strlen(str));
63    bytestream_put_buffer(dst, str, strlen(str));
64}
65
66void ff_amf_write_object_end(uint8_t **dst)
67{
68    /* first two bytes are field name length = 0,
69     * AMF object should end with it and end marker
70     */
71    bytestream_put_be24(dst, AMF_DATA_TYPE_OBJECT_END);
72}
73
74int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
75                        int chunk_size, RTMPPacket *prev_pkt)
76{
77    uint8_t hdr, t, buf[16];
78    int channel_id, timestamp, data_size, offset = 0;
79    uint32_t extra = 0;
80    enum RTMPPacketType type;
81    int size = 0;
82
83    if (ffurl_read(h, &hdr, 1) != 1)
84        return AVERROR(EIO);
85    size++;
86    channel_id = hdr & 0x3F;
87
88    if (channel_id < 2) { //special case for channel number >= 64
89        buf[1] = 0;
90        if (ffurl_read_complete(h, buf, channel_id + 1) != channel_id + 1)
91            return AVERROR(EIO);
92        size += channel_id + 1;
93        channel_id = AV_RL16(buf) + 64;
94    }
95    data_size = prev_pkt[channel_id].data_size;
96    type      = prev_pkt[channel_id].type;
97    extra     = prev_pkt[channel_id].extra;
98
99    hdr >>= 6;
100    if (hdr == RTMP_PS_ONEBYTE) {
101        timestamp = prev_pkt[channel_id].ts_delta;
102    } else {
103        if (ffurl_read_complete(h, buf, 3) != 3)
104            return AVERROR(EIO);
105        size += 3;
106        timestamp = AV_RB24(buf);
107        if (hdr != RTMP_PS_FOURBYTES) {
108            if (ffurl_read_complete(h, buf, 3) != 3)
109                return AVERROR(EIO);
110            size += 3;
111            data_size = AV_RB24(buf);
112            if (ffurl_read_complete(h, buf, 1) != 1)
113                return AVERROR(EIO);
114            size++;
115            type = buf[0];
116            if (hdr == RTMP_PS_TWELVEBYTES) {
117                if (ffurl_read_complete(h, buf, 4) != 4)
118                    return AVERROR(EIO);
119                size += 4;
120                extra = AV_RL32(buf);
121            }
122        }
123        if (timestamp == 0xFFFFFF) {
124            if (ffurl_read_complete(h, buf, 4) != 4)
125                return AVERROR(EIO);
126            timestamp = AV_RB32(buf);
127        }
128    }
129    if (hdr != RTMP_PS_TWELVEBYTES)
130        timestamp += prev_pkt[channel_id].timestamp;
131
132    if (ff_rtmp_packet_create(p, channel_id, type, timestamp, data_size))
133        return -1;
134    p->extra = extra;
135    // save history
136    prev_pkt[channel_id].channel_id = channel_id;
137    prev_pkt[channel_id].type       = type;
138    prev_pkt[channel_id].data_size  = data_size;
139    prev_pkt[channel_id].ts_delta   = timestamp - prev_pkt[channel_id].timestamp;
140    prev_pkt[channel_id].timestamp  = timestamp;
141    prev_pkt[channel_id].extra      = extra;
142    while (data_size > 0) {
143        int toread = FFMIN(data_size, chunk_size);
144        if (ffurl_read_complete(h, p->data + offset, toread) != toread) {
145            ff_rtmp_packet_destroy(p);
146            return AVERROR(EIO);
147        }
148        data_size -= chunk_size;
149        offset    += chunk_size;
150        size      += chunk_size;
151        if (data_size > 0) {
152            ffurl_read_complete(h, &t, 1); //marker
153            size++;
154            if (t != (0xC0 + channel_id))
155                return -1;
156        }
157    }
158    return size;
159}
160
161int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt,
162                         int chunk_size, RTMPPacket *prev_pkt)
163{
164    uint8_t pkt_hdr[16], *p = pkt_hdr;
165    int mode = RTMP_PS_TWELVEBYTES;
166    int off = 0;
167    int size = 0;
168
169    pkt->ts_delta = pkt->timestamp - prev_pkt[pkt->channel_id].timestamp;
170
171    //if channel_id = 0, this is first presentation of prev_pkt, send full hdr.
172    if (prev_pkt[pkt->channel_id].channel_id &&
173        pkt->extra == prev_pkt[pkt->channel_id].extra) {
174        if (pkt->type == prev_pkt[pkt->channel_id].type &&
175            pkt->data_size == prev_pkt[pkt->channel_id].data_size) {
176            mode = RTMP_PS_FOURBYTES;
177            if (pkt->ts_delta == prev_pkt[pkt->channel_id].ts_delta)
178                mode = RTMP_PS_ONEBYTE;
179        } else {
180            mode = RTMP_PS_EIGHTBYTES;
181        }
182    }
183
184    if (pkt->channel_id < 64) {
185        bytestream_put_byte(&p, pkt->channel_id | (mode << 6));
186    } else if (pkt->channel_id < 64 + 256) {
187        bytestream_put_byte(&p, 0               | (mode << 6));
188        bytestream_put_byte(&p, pkt->channel_id - 64);
189    } else {
190        bytestream_put_byte(&p, 1               | (mode << 6));
191        bytestream_put_le16(&p, pkt->channel_id - 64);
192    }
193    if (mode != RTMP_PS_ONEBYTE) {
194        uint32_t timestamp = pkt->timestamp;
195        if (mode != RTMP_PS_TWELVEBYTES)
196            timestamp = pkt->ts_delta;
197        bytestream_put_be24(&p, timestamp >= 0xFFFFFF ? 0xFFFFFF : timestamp);
198        if (mode != RTMP_PS_FOURBYTES) {
199            bytestream_put_be24(&p, pkt->data_size);
200            bytestream_put_byte(&p, pkt->type);
201            if (mode == RTMP_PS_TWELVEBYTES)
202                bytestream_put_le32(&p, pkt->extra);
203        }
204        if (timestamp >= 0xFFFFFF)
205            bytestream_put_be32(&p, timestamp);
206    }
207    // save history
208    prev_pkt[pkt->channel_id].channel_id = pkt->channel_id;
209    prev_pkt[pkt->channel_id].type       = pkt->type;
210    prev_pkt[pkt->channel_id].data_size  = pkt->data_size;
211    prev_pkt[pkt->channel_id].timestamp  = pkt->timestamp;
212    if (mode != RTMP_PS_TWELVEBYTES) {
213        prev_pkt[pkt->channel_id].ts_delta   = pkt->ts_delta;
214    } else {
215        prev_pkt[pkt->channel_id].ts_delta   = pkt->timestamp;
216    }
217    prev_pkt[pkt->channel_id].extra      = pkt->extra;
218
219    ffurl_write(h, pkt_hdr, p-pkt_hdr);
220    size = p - pkt_hdr + pkt->data_size;
221    while (off < pkt->data_size) {
222        int towrite = FFMIN(chunk_size, pkt->data_size - off);
223        ffurl_write(h, pkt->data + off, towrite);
224        off += towrite;
225        if (off < pkt->data_size) {
226            uint8_t marker = 0xC0 | pkt->channel_id;
227            ffurl_write(h, &marker, 1);
228            size++;
229        }
230    }
231    return size;
232}
233
234int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type,
235                          int timestamp, int size)
236{
237    if (size) {
238        pkt->data = av_malloc(size);
239        if (!pkt->data)
240            return AVERROR(ENOMEM);
241    }
242    pkt->data_size  = size;
243    pkt->channel_id = channel_id;
244    pkt->type       = type;
245    pkt->timestamp  = timestamp;
246    pkt->extra      = 0;
247    pkt->ts_delta   = 0;
248
249    return 0;
250}
251
252void ff_rtmp_packet_destroy(RTMPPacket *pkt)
253{
254    if (!pkt)
255        return;
256    av_freep(&pkt->data);
257    pkt->data_size = 0;
258}
259
260int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
261{
262    const uint8_t *base = data;
263
264    if (data >= data_end)
265        return -1;
266    switch (*data++) {
267    case AMF_DATA_TYPE_NUMBER:      return 9;
268    case AMF_DATA_TYPE_BOOL:        return 2;
269    case AMF_DATA_TYPE_STRING:      return 3 + AV_RB16(data);
270    case AMF_DATA_TYPE_LONG_STRING: return 5 + AV_RB32(data);
271    case AMF_DATA_TYPE_NULL:        return 1;
272    case AMF_DATA_TYPE_ARRAY:
273        data += 4;
274    case AMF_DATA_TYPE_OBJECT:
275        for (;;) {
276            int size = bytestream_get_be16(&data);
277            int t;
278            if (!size) {
279                data++;
280                break;
281            }
282            if (data + size >= data_end || data + size < data)
283                return -1;
284            data += size;
285            t = ff_amf_tag_size(data, data_end);
286            if (t < 0 || data + t >= data_end)
287                return -1;
288            data += t;
289        }
290        return data - base;
291    case AMF_DATA_TYPE_OBJECT_END:  return 1;
292    default:                        return -1;
293    }
294}
295
296int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end,
297                           const uint8_t *name, uint8_t *dst, int dst_size)
298{
299    int namelen = strlen(name);
300    int len;
301
302    while (*data != AMF_DATA_TYPE_OBJECT && data < data_end) {
303        len = ff_amf_tag_size(data, data_end);
304        if (len < 0)
305            len = data_end - data;
306        data += len;
307    }
308    if (data_end - data < 3)
309        return -1;
310    data++;
311    for (;;) {
312        int size = bytestream_get_be16(&data);
313        if (!size)
314            break;
315        if (data + size >= data_end || data + size < data)
316            return -1;
317        data += size;
318        if (size == namelen && !memcmp(data-size, name, namelen)) {
319            switch (*data++) {
320            case AMF_DATA_TYPE_NUMBER:
321                snprintf(dst, dst_size, "%g", av_int2double(AV_RB64(data)));
322                break;
323            case AMF_DATA_TYPE_BOOL:
324                snprintf(dst, dst_size, "%s", *data ? "true" : "false");
325                break;
326            case AMF_DATA_TYPE_STRING:
327                len = bytestream_get_be16(&data);
328                av_strlcpy(dst, data, FFMIN(len+1, dst_size));
329                break;
330            default:
331                return -1;
332            }
333            return 0;
334        }
335        len = ff_amf_tag_size(data, data_end);
336        if (len < 0 || data + len >= data_end || data + len < data)
337            return -1;
338        data += len;
339    }
340    return -1;
341}
342
343static const char* rtmp_packet_type(int type)
344{
345    switch (type) {
346    case RTMP_PT_CHUNK_SIZE:     return "chunk size";
347    case RTMP_PT_BYTES_READ:     return "bytes read";
348    case RTMP_PT_PING:           return "ping";
349    case RTMP_PT_SERVER_BW:      return "server bandwidth";
350    case RTMP_PT_CLIENT_BW:      return "client bandwidth";
351    case RTMP_PT_AUDIO:          return "audio packet";
352    case RTMP_PT_VIDEO:          return "video packet";
353    case RTMP_PT_FLEX_STREAM:    return "Flex shared stream";
354    case RTMP_PT_FLEX_OBJECT:    return "Flex shared object";
355    case RTMP_PT_FLEX_MESSAGE:   return "Flex shared message";
356    case RTMP_PT_NOTIFY:         return "notification";
357    case RTMP_PT_SHARED_OBJ:     return "shared object";
358    case RTMP_PT_INVOKE:         return "invoke";
359    case RTMP_PT_METADATA:       return "metadata";
360    default:                     return "unknown";
361    }
362}
363
364static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end)
365{
366    int size;
367    char buf[1024];
368
369    if (data >= data_end)
370        return;
371    switch (*data++) {
372    case AMF_DATA_TYPE_NUMBER:
373        av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2double(AV_RB64(data)));
374        return;
375    case AMF_DATA_TYPE_BOOL:
376        av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data);
377        return;
378    case AMF_DATA_TYPE_STRING:
379    case AMF_DATA_TYPE_LONG_STRING:
380        if (data[-1] == AMF_DATA_TYPE_STRING) {
381            size = bytestream_get_be16(&data);
382        } else {
383            size = bytestream_get_be32(&data);
384        }
385        size = FFMIN(size, 1023);
386        memcpy(buf, data, size);
387        buf[size] = 0;
388        av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf);
389        return;
390    case AMF_DATA_TYPE_NULL:
391        av_log(ctx, AV_LOG_DEBUG, " NULL\n");
392        return;
393    case AMF_DATA_TYPE_ARRAY:
394        data += 4;
395    case AMF_DATA_TYPE_OBJECT:
396        av_log(ctx, AV_LOG_DEBUG, " {\n");
397        for (;;) {
398            int size = bytestream_get_be16(&data);
399            int t;
400            memcpy(buf, data, size);
401            buf[size] = 0;
402            if (!size) {
403                av_log(ctx, AV_LOG_DEBUG, " }\n");
404                data++;
405                break;
406            }
407            if (data + size >= data_end || data + size < data)
408                return;
409            data += size;
410            av_log(ctx, AV_LOG_DEBUG, "  %s: ", buf);
411            ff_amf_tag_contents(ctx, data, data_end);
412            t = ff_amf_tag_size(data, data_end);
413            if (t < 0 || data + t >= data_end)
414                return;
415            data += t;
416        }
417        return;
418    case AMF_DATA_TYPE_OBJECT_END:
419        av_log(ctx, AV_LOG_DEBUG, " }\n");
420        return;
421    default:
422        return;
423    }
424}
425
426void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
427{
428    av_log(ctx, AV_LOG_DEBUG, "RTMP packet type '%s'(%d) for channel %d, timestamp %d, extra field %d size %d\n",
429           rtmp_packet_type(p->type), p->type, p->channel_id, p->timestamp, p->extra, p->data_size);
430    if (p->type == RTMP_PT_INVOKE || p->type == RTMP_PT_NOTIFY) {
431        uint8_t *src = p->data, *src_end = p->data + p->data_size;
432        while (src < src_end) {
433            int sz;
434            ff_amf_tag_contents(ctx, src, src_end);
435            sz = ff_amf_tag_size(src, src_end);
436            if (sz < 0)
437                break;
438            src += sz;
439        }
440    } else if (p->type == RTMP_PT_SERVER_BW){
441        av_log(ctx, AV_LOG_DEBUG, "Server BW = %d\n", AV_RB32(p->data));
442    } else if (p->type == RTMP_PT_CLIENT_BW){
443        av_log(ctx, AV_LOG_DEBUG, "Client BW = %d\n", AV_RB32(p->data));
444    } else if (p->type != RTMP_PT_AUDIO && p->type != RTMP_PT_VIDEO && p->type != RTMP_PT_METADATA) {
445        int i;
446        for (i = 0; i < p->data_size; i++)
447            av_log(ctx, AV_LOG_DEBUG, " %02X", p->data[i]);
448        av_log(ctx, AV_LOG_DEBUG, "\n");
449    }
450}
451