~ubuntu-branches/ubuntu/trusty/libav/trusty-proposed

« back to all changes in this revision

Viewing changes to libavformat/rtmppkt.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2013-10-22 23:24:08 UTC
  • mfrom: (1.3.36 sid)
  • Revision ID: package-import@ubuntu.com-20131022232408-b8tvvn4pyzri9mi3
Tags: 6:9.10-1ubuntu1
* Build all -extra flavors from this source package, as libav got demoted
  from main to universe, cf LP: #1243235
* Simplify debian/rules to follow exactly the code that debian executes
* New upstream (LP: #1180288) fixes lots of security issues (LP: #1242802)
* Merge from unstable, remaining changes:
  - build-depend on libtiff5-dev rather than libtiff4-dev,
    avoids FTBFS caused by imlib
  - follow the regular debian codepaths

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
    bytestream_put_buffer(dst, str, strlen(str));
48
48
}
49
49
 
 
50
void ff_amf_write_string2(uint8_t **dst, const char *str1, const char *str2)
 
51
{
 
52
    int len1 = 0, len2 = 0;
 
53
    if (str1)
 
54
        len1 = strlen(str1);
 
55
    if (str2)
 
56
        len2 = strlen(str2);
 
57
    bytestream_put_byte(dst, AMF_DATA_TYPE_STRING);
 
58
    bytestream_put_be16(dst, len1 + len2);
 
59
    bytestream_put_buffer(dst, str1, len1);
 
60
    bytestream_put_buffer(dst, str2, len2);
 
61
}
 
62
 
50
63
void ff_amf_write_null(uint8_t **dst)
51
64
{
52
65
    bytestream_put_byte(dst, AMF_DATA_TYPE_NULL);
71
84
    bytestream_put_be24(dst, AMF_DATA_TYPE_OBJECT_END);
72
85
}
73
86
 
 
87
int ff_amf_read_bool(GetByteContext *bc, int *val)
 
88
{
 
89
    if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_BOOL)
 
90
        return AVERROR_INVALIDDATA;
 
91
    *val = bytestream2_get_byte(bc);
 
92
    return 0;
 
93
}
 
94
 
 
95
int ff_amf_read_number(GetByteContext *bc, double *val)
 
96
{
 
97
    uint64_t read;
 
98
    if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_NUMBER)
 
99
        return AVERROR_INVALIDDATA;
 
100
    read = bytestream2_get_be64(bc);
 
101
    *val = av_int2double(read);
 
102
    return 0;
 
103
}
 
104
 
 
105
int ff_amf_read_string(GetByteContext *bc, uint8_t *str,
 
106
                       int strsize, int *length)
 
107
{
 
108
    int stringlen = 0;
 
109
    int readsize;
 
110
    if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_STRING)
 
111
        return AVERROR_INVALIDDATA;
 
112
    stringlen = bytestream2_get_be16(bc);
 
113
    if (stringlen + 1 > strsize)
 
114
        return AVERROR(EINVAL);
 
115
    readsize = bytestream2_get_buffer(bc, str, stringlen);
 
116
    if (readsize != stringlen) {
 
117
        av_log(NULL, AV_LOG_WARNING,
 
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
 
 
125
int ff_amf_read_null(GetByteContext *bc)
 
126
{
 
127
    if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_NULL)
 
128
        return AVERROR_INVALIDDATA;
 
129
    return 0;
 
130
}
 
131
 
74
132
int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
75
133
                        int chunk_size, RTMPPacket *prev_pkt)
76
134
{
77
 
    uint8_t hdr, t, buf[16];
78
 
    int channel_id, timestamp, data_size, offset = 0;
 
135
    uint8_t hdr;
 
136
 
 
137
    if (ffurl_read(h, &hdr, 1) != 1)
 
138
        return AVERROR(EIO);
 
139
 
 
140
    return ff_rtmp_packet_read_internal(h, p, chunk_size, prev_pkt, hdr);
 
141
}
 
142
 
 
143
int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size,
 
144
                                 RTMPPacket *prev_pkt, uint8_t hdr)
 
145
{
 
146
 
 
147
    uint8_t t, buf[16];
 
148
    int channel_id, timestamp, size, offset = 0;
79
149
    uint32_t extra = 0;
80
150
    enum RTMPPacketType type;
81
 
    int size = 0;
 
151
    int written = 0;
 
152
    int ret;
82
153
 
83
 
    if (ffurl_read(h, &hdr, 1) != 1)
84
 
        return AVERROR(EIO);
85
 
    size++;
 
154
    written++;
86
155
    channel_id = hdr & 0x3F;
87
156
 
88
157
    if (channel_id < 2) { //special case for channel number >= 64
89
158
        buf[1] = 0;
90
159
        if (ffurl_read_complete(h, buf, channel_id + 1) != channel_id + 1)
91
160
            return AVERROR(EIO);
92
 
        size += channel_id + 1;
 
161
        written += channel_id + 1;
93
162
        channel_id = AV_RL16(buf) + 64;
94
163
    }
95
 
    data_size = prev_pkt[channel_id].data_size;
96
 
    type      = prev_pkt[channel_id].type;
97
 
    extra     = prev_pkt[channel_id].extra;
 
164
    size  = prev_pkt[channel_id].size;
 
165
    type  = prev_pkt[channel_id].type;
 
166
    extra = prev_pkt[channel_id].extra;
98
167
 
99
168
    hdr >>= 6;
100
169
    if (hdr == RTMP_PS_ONEBYTE) {
102
171
    } else {
103
172
        if (ffurl_read_complete(h, buf, 3) != 3)
104
173
            return AVERROR(EIO);
105
 
        size += 3;
 
174
        written += 3;
106
175
        timestamp = AV_RB24(buf);
107
176
        if (hdr != RTMP_PS_FOURBYTES) {
108
177
            if (ffurl_read_complete(h, buf, 3) != 3)
109
178
                return AVERROR(EIO);
110
 
            size += 3;
111
 
            data_size = AV_RB24(buf);
 
179
            written += 3;
 
180
            size = AV_RB24(buf);
112
181
            if (ffurl_read_complete(h, buf, 1) != 1)
113
182
                return AVERROR(EIO);
114
 
            size++;
 
183
            written++;
115
184
            type = buf[0];
116
185
            if (hdr == RTMP_PS_TWELVEBYTES) {
117
186
                if (ffurl_read_complete(h, buf, 4) != 4)
118
187
                    return AVERROR(EIO);
119
 
                size += 4;
 
188
                written += 4;
120
189
                extra = AV_RL32(buf);
121
190
            }
122
191
        }
129
198
    if (hdr != RTMP_PS_TWELVEBYTES)
130
199
        timestamp += prev_pkt[channel_id].timestamp;
131
200
 
132
 
    if (ff_rtmp_packet_create(p, channel_id, type, timestamp, data_size))
133
 
        return -1;
 
201
    if ((ret = ff_rtmp_packet_create(p, channel_id, type, timestamp,
 
202
                                     size)) < 0)
 
203
        return ret;
134
204
    p->extra = extra;
135
205
    // save history
136
206
    prev_pkt[channel_id].channel_id = channel_id;
137
207
    prev_pkt[channel_id].type       = type;
138
 
    prev_pkt[channel_id].data_size  = data_size;
 
208
    prev_pkt[channel_id].size       = size;
139
209
    prev_pkt[channel_id].ts_delta   = timestamp - prev_pkt[channel_id].timestamp;
140
210
    prev_pkt[channel_id].timestamp  = timestamp;
141
211
    prev_pkt[channel_id].extra      = extra;
142
 
    while (data_size > 0) {
143
 
        int toread = FFMIN(data_size, chunk_size);
 
212
    while (size > 0) {
 
213
        int toread = FFMIN(size, chunk_size);
144
214
        if (ffurl_read_complete(h, p->data + offset, toread) != toread) {
145
215
            ff_rtmp_packet_destroy(p);
146
216
            return AVERROR(EIO);
147
217
        }
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++;
 
218
        size    -= chunk_size;
 
219
        offset  += chunk_size;
 
220
        written += chunk_size;
 
221
        if (size > 0) {
 
222
            if ((ret = ffurl_read_complete(h, &t, 1)) < 0) { // marker
 
223
                ff_rtmp_packet_destroy(p);
 
224
                return ret;
 
225
            }
 
226
            written++;
154
227
            if (t != (0xC0 + channel_id))
155
228
                return -1;
156
229
        }
157
230
    }
158
 
    return size;
 
231
    return written;
159
232
}
160
233
 
161
234
int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt,
164
237
    uint8_t pkt_hdr[16], *p = pkt_hdr;
165
238
    int mode = RTMP_PS_TWELVEBYTES;
166
239
    int off = 0;
167
 
    int size = 0;
 
240
    int written = 0;
 
241
    int ret;
168
242
 
169
243
    pkt->ts_delta = pkt->timestamp - prev_pkt[pkt->channel_id].timestamp;
170
244
 
172
246
    if (prev_pkt[pkt->channel_id].channel_id &&
173
247
        pkt->extra == prev_pkt[pkt->channel_id].extra) {
174
248
        if (pkt->type == prev_pkt[pkt->channel_id].type &&
175
 
            pkt->data_size == prev_pkt[pkt->channel_id].data_size) {
 
249
            pkt->size == prev_pkt[pkt->channel_id].size) {
176
250
            mode = RTMP_PS_FOURBYTES;
177
251
            if (pkt->ts_delta == prev_pkt[pkt->channel_id].ts_delta)
178
252
                mode = RTMP_PS_ONEBYTE;
196
270
            timestamp = pkt->ts_delta;
197
271
        bytestream_put_be24(&p, timestamp >= 0xFFFFFF ? 0xFFFFFF : timestamp);
198
272
        if (mode != RTMP_PS_FOURBYTES) {
199
 
            bytestream_put_be24(&p, pkt->data_size);
 
273
            bytestream_put_be24(&p, pkt->size);
200
274
            bytestream_put_byte(&p, pkt->type);
201
275
            if (mode == RTMP_PS_TWELVEBYTES)
202
276
                bytestream_put_le32(&p, pkt->extra);
207
281
    // save history
208
282
    prev_pkt[pkt->channel_id].channel_id = pkt->channel_id;
209
283
    prev_pkt[pkt->channel_id].type       = pkt->type;
210
 
    prev_pkt[pkt->channel_id].data_size  = pkt->data_size;
 
284
    prev_pkt[pkt->channel_id].size       = pkt->size;
211
285
    prev_pkt[pkt->channel_id].timestamp  = pkt->timestamp;
212
286
    if (mode != RTMP_PS_TWELVEBYTES) {
213
287
        prev_pkt[pkt->channel_id].ts_delta   = pkt->ts_delta;
216
290
    }
217
291
    prev_pkt[pkt->channel_id].extra      = pkt->extra;
218
292
 
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);
 
293
    if ((ret = ffurl_write(h, pkt_hdr, p - pkt_hdr)) < 0)
 
294
        return ret;
 
295
    written = p - pkt_hdr + pkt->size;
 
296
    while (off < pkt->size) {
 
297
        int towrite = FFMIN(chunk_size, pkt->size - off);
 
298
        if ((ret = ffurl_write(h, pkt->data + off, towrite)) < 0)
 
299
            return ret;
224
300
        off += towrite;
225
 
        if (off < pkt->data_size) {
 
301
        if (off < pkt->size) {
226
302
            uint8_t marker = 0xC0 | pkt->channel_id;
227
 
            ffurl_write(h, &marker, 1);
228
 
            size++;
 
303
            if ((ret = ffurl_write(h, &marker, 1)) < 0)
 
304
                return ret;
 
305
            written++;
229
306
        }
230
307
    }
231
 
    return size;
 
308
    return written;
232
309
}
233
310
 
234
311
int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type,
239
316
        if (!pkt->data)
240
317
            return AVERROR(ENOMEM);
241
318
    }
242
 
    pkt->data_size  = size;
 
319
    pkt->size       = size;
243
320
    pkt->channel_id = channel_id;
244
321
    pkt->type       = type;
245
322
    pkt->timestamp  = timestamp;
254
331
    if (!pkt)
255
332
        return;
256
333
    av_freep(&pkt->data);
257
 
    pkt->data_size = 0;
 
334
    pkt->size = 0;
258
335
}
259
336
 
260
337
int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
426
503
void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
427
504
{
428
505
    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);
 
506
           rtmp_packet_type(p->type), p->type, p->channel_id, p->timestamp, p->extra, p->size);
430
507
    if (p->type == RTMP_PT_INVOKE || p->type == RTMP_PT_NOTIFY) {
431
 
        uint8_t *src = p->data, *src_end = p->data + p->data_size;
 
508
        uint8_t *src = p->data, *src_end = p->data + p->size;
432
509
        while (src < src_end) {
433
510
            int sz;
434
511
            ff_amf_tag_contents(ctx, src, src_end);
443
520
        av_log(ctx, AV_LOG_DEBUG, "Client BW = %d\n", AV_RB32(p->data));
444
521
    } else if (p->type != RTMP_PT_AUDIO && p->type != RTMP_PT_VIDEO && p->type != RTMP_PT_METADATA) {
445
522
        int i;
446
 
        for (i = 0; i < p->data_size; i++)
 
523
        for (i = 0; i < p->size; i++)
447
524
            av_log(ctx, AV_LOG_DEBUG, " %02X", p->data[i]);
448
525
        av_log(ctx, AV_LOG_DEBUG, "\n");
449
526
    }
450
527
}
 
528
 
 
529
int ff_amf_match_string(const uint8_t *data, int size, const char *str)
 
530
{
 
531
    int len = strlen(str);
 
532
    int amf_len, type;
 
533
 
 
534
    if (size < 1)
 
535
        return 0;
 
536
 
 
537
    type = *data++;
 
538
 
 
539
    if (type != AMF_DATA_TYPE_LONG_STRING &&
 
540
        type != AMF_DATA_TYPE_STRING)
 
541
        return 0;
 
542
 
 
543
    if (type == AMF_DATA_TYPE_LONG_STRING) {
 
544
        if ((size -= 4 + 1) < 0)
 
545
            return 0;
 
546
        amf_len = bytestream_get_be32(&data);
 
547
    } else {
 
548
        if ((size -= 2 + 1) < 0)
 
549
            return 0;
 
550
        amf_len = bytestream_get_be16(&data);
 
551
    }
 
552
 
 
553
    if (amf_len > size)
 
554
        return 0;
 
555
 
 
556
    if (amf_len != len)
 
557
        return 0;
 
558
 
 
559
    return !memcmp(data, str, len);
 
560
}