Statistics
| Branch: | Revision:

ffmpeg / libavformat / rtpdec.c @ 06a36faf

History | View | Annotate | Download (19.5 KB)

1
/*
2
 * RTP input format
3
 * Copyright (c) 2002 Fabrice Bellard
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

    
22
/* needed for gethostname() */
23
#define _XOPEN_SOURCE 600
24

    
25
#include "libavcodec/get_bits.h"
26
#include "avformat.h"
27
#include "mpegts.h"
28

    
29
#include <unistd.h>
30
#include "network.h"
31

    
32
#include "rtpdec.h"
33
#include "rtpdec_amr.h"
34
#include "rtpdec_asf.h"
35
#include "rtpdec_h263.h"
36
#include "rtpdec_h264.h"
37
#include "rtpdec_xiph.h"
38

    
39
//#define DEBUG
40

    
41
/* TODO: - add RTCP statistics reporting (should be optional).
42

43
         - add support for h263/mpeg4 packetized output : IDEA: send a
44
         buffer to 'rtp_write_packet' contains all the packets for ONE
45
         frame. Each packet should have a four byte header containing
46
         the length in big endian format (same trick as
47
         'url_open_dyn_packet_buf')
48
*/
49

    
50
/* statistics functions */
51
RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler= NULL;
52

    
53
static RTPDynamicProtocolHandler mp4v_es_handler= {"MP4V-ES", AVMEDIA_TYPE_VIDEO, CODEC_ID_MPEG4};
54
static RTPDynamicProtocolHandler mpeg4_generic_handler= {"mpeg4-generic", AVMEDIA_TYPE_AUDIO, CODEC_ID_AAC};
55

    
56
void ff_register_dynamic_payload_handler(RTPDynamicProtocolHandler *handler)
57
{
58
    handler->next= RTPFirstDynamicPayloadHandler;
59
    RTPFirstDynamicPayloadHandler= handler;
60
}
61

    
62
void av_register_rtp_dynamic_payload_handlers(void)
63
{
64
    ff_register_dynamic_payload_handler(&mp4v_es_handler);
65
    ff_register_dynamic_payload_handler(&mpeg4_generic_handler);
66
    ff_register_dynamic_payload_handler(&ff_amr_nb_dynamic_handler);
67
    ff_register_dynamic_payload_handler(&ff_amr_wb_dynamic_handler);
68
    ff_register_dynamic_payload_handler(&ff_h263_1998_dynamic_handler);
69
    ff_register_dynamic_payload_handler(&ff_h263_2000_dynamic_handler);
70
    ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler);
71
    ff_register_dynamic_payload_handler(&ff_vorbis_dynamic_handler);
72
    ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler);
73

    
74
    ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler);
75
    ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfa_handler);
76
}
77

    
78
static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int len)
79
{
80
    if (buf[1] != 200)
81
        return -1;
82
    s->last_rtcp_ntp_time = AV_RB64(buf + 8);
83
    s->last_rtcp_timestamp = AV_RB32(buf + 16);
84
    return 0;
85
}
86

    
87
#define RTP_SEQ_MOD (1<<16)
88

    
89
/**
90
* called on parse open packet
91
*/
92
static void rtp_init_statistics(RTPStatistics *s, uint16_t base_sequence) // called on parse open packet.
93
{
94
    memset(s, 0, sizeof(RTPStatistics));
95
    s->max_seq= base_sequence;
96
    s->probation= 1;
97
}
98

    
99
/**
100
* called whenever there is a large jump in sequence numbers, or when they get out of probation...
101
*/
102
static void rtp_init_sequence(RTPStatistics *s, uint16_t seq)
103
{
104
    s->max_seq= seq;
105
    s->cycles= 0;
106
    s->base_seq= seq -1;
107
    s->bad_seq= RTP_SEQ_MOD + 1;
108
    s->received= 0;
109
    s->expected_prior= 0;
110
    s->received_prior= 0;
111
    s->jitter= 0;
112
    s->transit= 0;
113
}
114

    
115
/**
116
* returns 1 if we should handle this packet.
117
*/
118
static int rtp_valid_packet_in_sequence(RTPStatistics *s, uint16_t seq)
119
{
120
    uint16_t udelta= seq - s->max_seq;
121
    const int MAX_DROPOUT= 3000;
122
    const int MAX_MISORDER = 100;
123
    const int MIN_SEQUENTIAL = 2;
124

    
125
    /* source not valid until MIN_SEQUENTIAL packets with sequence seq. numbers have been received */
126
    if(s->probation)
127
    {
128
        if(seq==s->max_seq + 1) {
129
            s->probation--;
130
            s->max_seq= seq;
131
            if(s->probation==0) {
132
                rtp_init_sequence(s, seq);
133
                s->received++;
134
                return 1;
135
            }
136
        } else {
137
            s->probation= MIN_SEQUENTIAL - 1;
138
            s->max_seq = seq;
139
        }
140
    } else if (udelta < MAX_DROPOUT) {
141
        // in order, with permissible gap
142
        if(seq < s->max_seq) {
143
            //sequence number wrapped; count antother 64k cycles
144
            s->cycles += RTP_SEQ_MOD;
145
        }
146
        s->max_seq= seq;
147
    } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
148
        // sequence made a large jump...
149
        if(seq==s->bad_seq) {
150
            // two sequential packets-- assume that the other side restarted without telling us; just resync.
151
            rtp_init_sequence(s, seq);
152
        } else {
153
            s->bad_seq= (seq + 1) & (RTP_SEQ_MOD-1);
154
            return 0;
155
        }
156
    } else {
157
        // duplicate or reordered packet...
158
    }
159
    s->received++;
160
    return 1;
161
}
162

    
163
#if 0
164
/**
165
* This function is currently unused; without a valid local ntp time, I don't see how we could calculate the
166
* difference between the arrival and sent timestamp.  As a result, the jitter and transit statistics values
167
* never change.  I left this in in case someone else can see a way. (rdm)
168
*/
169
static void rtcp_update_jitter(RTPStatistics *s, uint32_t sent_timestamp, uint32_t arrival_timestamp)
170
{
171
    uint32_t transit= arrival_timestamp - sent_timestamp;
172
    int d;
173
    s->transit= transit;
174
    d= FFABS(transit - s->transit);
175
    s->jitter += d - ((s->jitter + 8)>>4);
176
}
177
#endif
178

    
179
int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count)
180
{
181
    ByteIOContext *pb;
182
    uint8_t *buf;
183
    int len;
184
    int rtcp_bytes;
185
    RTPStatistics *stats= &s->statistics;
186
    uint32_t lost;
187
    uint32_t extended_max;
188
    uint32_t expected_interval;
189
    uint32_t received_interval;
190
    uint32_t lost_interval;
191
    uint32_t expected;
192
    uint32_t fraction;
193
    uint64_t ntp_time= s->last_rtcp_ntp_time; // TODO: Get local ntp time?
194

    
195
    if (!s->rtp_ctx || (count < 1))
196
        return -1;
197

    
198
    /* TODO: I think this is way too often; RFC 1889 has algorithm for this */
199
    /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
200
    s->octet_count += count;
201
    rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) /
202
        RTCP_TX_RATIO_DEN;
203
    rtcp_bytes /= 50; // mmu_man: that's enough for me... VLC sends much less btw !?
204
    if (rtcp_bytes < 28)
205
        return -1;
206
    s->last_octet_count = s->octet_count;
207

    
208
    if (url_open_dyn_buf(&pb) < 0)
209
        return -1;
210

    
211
    // Receiver Report
212
    put_byte(pb, (RTP_VERSION << 6) + 1); /* 1 report block */
213
    put_byte(pb, 201);
214
    put_be16(pb, 7); /* length in words - 1 */
215
    put_be32(pb, s->ssrc); // our own SSRC
216
    put_be32(pb, s->ssrc); // XXX: should be the server's here!
217
    // some placeholders we should really fill...
218
    // RFC 1889/p64
219
    extended_max= stats->cycles + stats->max_seq;
220
    expected= extended_max - stats->base_seq + 1;
221
    lost= expected - stats->received;
222
    lost= FFMIN(lost, 0xffffff); // clamp it since it's only 24 bits...
223
    expected_interval= expected - stats->expected_prior;
224
    stats->expected_prior= expected;
225
    received_interval= stats->received - stats->received_prior;
226
    stats->received_prior= stats->received;
227
    lost_interval= expected_interval - received_interval;
228
    if (expected_interval==0 || lost_interval<=0) fraction= 0;
229
    else fraction = (lost_interval<<8)/expected_interval;
230

    
231
    fraction= (fraction<<24) | lost;
232

    
233
    put_be32(pb, fraction); /* 8 bits of fraction, 24 bits of total packets lost */
234
    put_be32(pb, extended_max); /* max sequence received */
235
    put_be32(pb, stats->jitter>>4); /* jitter */
236

    
237
    if(s->last_rtcp_ntp_time==AV_NOPTS_VALUE)
238
    {
239
        put_be32(pb, 0); /* last SR timestamp */
240
        put_be32(pb, 0); /* delay since last SR */
241
    } else {
242
        uint32_t middle_32_bits= s->last_rtcp_ntp_time>>16; // this is valid, right? do we need to handle 64 bit values special?
243
        uint32_t delay_since_last= ntp_time - s->last_rtcp_ntp_time;
244

    
245
        put_be32(pb, middle_32_bits); /* last SR timestamp */
246
        put_be32(pb, delay_since_last); /* delay since last SR */
247
    }
248

    
249
    // CNAME
250
    put_byte(pb, (RTP_VERSION << 6) + 1); /* 1 report block */
251
    put_byte(pb, 202);
252
    len = strlen(s->hostname);
253
    put_be16(pb, (6 + len + 3) / 4); /* length in words - 1 */
254
    put_be32(pb, s->ssrc);
255
    put_byte(pb, 0x01);
256
    put_byte(pb, len);
257
    put_buffer(pb, s->hostname, len);
258
    // padding
259
    for (len = (6 + len) % 4; len % 4; len++) {
260
        put_byte(pb, 0);
261
    }
262

    
263
    put_flush_packet(pb);
264
    len = url_close_dyn_buf(pb, &buf);
265
    if ((len > 0) && buf) {
266
        int result;
267
        dprintf(s->ic, "sending %d bytes of RR\n", len);
268
        result= url_write(s->rtp_ctx, buf, len);
269
        dprintf(s->ic, "result from url_write: %d\n", result);
270
        av_free(buf);
271
    }
272
    return 0;
273
}
274

    
275
void rtp_send_punch_packets(URLContext* rtp_handle)
276
{
277
    ByteIOContext *pb;
278
    uint8_t *buf;
279
    int len;
280

    
281
    /* Send a small RTP packet */
282
    if (url_open_dyn_buf(&pb) < 0)
283
        return;
284

    
285
    put_byte(pb, (RTP_VERSION << 6));
286
    put_byte(pb, 0); /* Payload type */
287
    put_be16(pb, 0); /* Seq */
288
    put_be32(pb, 0); /* Timestamp */
289
    put_be32(pb, 0); /* SSRC */
290

    
291
    put_flush_packet(pb);
292
    len = url_close_dyn_buf(pb, &buf);
293
    if ((len > 0) && buf)
294
        url_write(rtp_handle, buf, len);
295
    av_free(buf);
296

    
297
    /* Send a minimal RTCP RR */
298
    if (url_open_dyn_buf(&pb) < 0)
299
        return;
300

    
301
    put_byte(pb, (RTP_VERSION << 6));
302
    put_byte(pb, 201); /* receiver report */
303
    put_be16(pb, 1); /* length in words - 1 */
304
    put_be32(pb, 0); /* our own SSRC */
305

    
306
    put_flush_packet(pb);
307
    len = url_close_dyn_buf(pb, &buf);
308
    if ((len > 0) && buf)
309
        url_write(rtp_handle, buf, len);
310
    av_free(buf);
311
}
312

    
313

    
314
/**
315
 * open a new RTP parse context for stream 'st'. 'st' can be NULL for
316
 * MPEG2TS streams to indicate that they should be demuxed inside the
317
 * rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned)
318
 * TODO: change this to not take rtp_payload data, and use the new dynamic payload system.
319
 */
320
RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, RTPPayloadData *rtp_payload_data)
321
{
322
    RTPDemuxContext *s;
323

    
324
    s = av_mallocz(sizeof(RTPDemuxContext));
325
    if (!s)
326
        return NULL;
327
    s->payload_type = payload_type;
328
    s->last_rtcp_ntp_time = AV_NOPTS_VALUE;
329
    s->ic = s1;
330
    s->st = st;
331
    s->rtp_payload_data = rtp_payload_data;
332
    rtp_init_statistics(&s->statistics, 0); // do we know the initial sequence from sdp?
333
    if (!strcmp(ff_rtp_enc_name(payload_type), "MP2T")) {
334
        s->ts = ff_mpegts_parse_open(s->ic);
335
        if (s->ts == NULL) {
336
            av_free(s);
337
            return NULL;
338
        }
339
    } else {
340
        av_set_pts_info(st, 32, 1, 90000);
341
        switch(st->codec->codec_id) {
342
        case CODEC_ID_MPEG1VIDEO:
343
        case CODEC_ID_MPEG2VIDEO:
344
        case CODEC_ID_MP2:
345
        case CODEC_ID_MP3:
346
        case CODEC_ID_MPEG4:
347
        case CODEC_ID_H263:
348
        case CODEC_ID_H264:
349
            st->need_parsing = AVSTREAM_PARSE_FULL;
350
            break;
351
        default:
352
            if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
353
                av_set_pts_info(st, 32, 1, st->codec->sample_rate);
354
            }
355
            break;
356
        }
357
    }
358
    // needed to send back RTCP RR in RTSP sessions
359
    s->rtp_ctx = rtpc;
360
    gethostname(s->hostname, sizeof(s->hostname));
361
    return s;
362
}
363

    
364
void
365
rtp_parse_set_dynamic_protocol(RTPDemuxContext *s, PayloadContext *ctx,
366
                               RTPDynamicProtocolHandler *handler)
367
{
368
    s->dynamic_protocol_context = ctx;
369
    s->parse_packet = handler->parse_packet;
370
}
371

    
372
static int rtp_parse_mp4_au(RTPDemuxContext *s, const uint8_t *buf)
373
{
374
    int au_headers_length, au_header_size, i;
375
    GetBitContext getbitcontext;
376
    RTPPayloadData *infos;
377

    
378
    infos = s->rtp_payload_data;
379

    
380
    if (infos == NULL)
381
        return -1;
382

    
383
    /* decode the first 2 bytes where the AUHeader sections are stored
384
       length in bits */
385
    au_headers_length = AV_RB16(buf);
386

    
387
    if (au_headers_length > RTP_MAX_PACKET_LENGTH)
388
      return -1;
389

    
390
    infos->au_headers_length_bytes = (au_headers_length + 7) / 8;
391

    
392
    /* skip AU headers length section (2 bytes) */
393
    buf += 2;
394

    
395
    init_get_bits(&getbitcontext, buf, infos->au_headers_length_bytes * 8);
396

    
397
    /* XXX: Wrong if optionnal additional sections are present (cts, dts etc...) */
398
    au_header_size = infos->sizelength + infos->indexlength;
399
    if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
400
        return -1;
401

    
402
    infos->nb_au_headers = au_headers_length / au_header_size;
403
    infos->au_headers = av_malloc(sizeof(struct AUHeaders) * infos->nb_au_headers);
404

    
405
    /* XXX: We handle multiple AU Section as only one (need to fix this for interleaving)
406
       In my test, the FAAD decoder does not behave correctly when sending each AU one by one
407
       but does when sending the whole as one big packet...  */
408
    infos->au_headers[0].size = 0;
409
    infos->au_headers[0].index = 0;
410
    for (i = 0; i < infos->nb_au_headers; ++i) {
411
        infos->au_headers[0].size += get_bits_long(&getbitcontext, infos->sizelength);
412
        infos->au_headers[0].index = get_bits_long(&getbitcontext, infos->indexlength);
413
    }
414

    
415
    infos->nb_au_headers = 1;
416

    
417
    return 0;
418
}
419

    
420
/**
421
 * This was the second switch in rtp_parse packet.  Normalizes time, if required, sets stream_index, etc.
422
 */
423
static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestamp)
424
{
425
    if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) {
426
        int64_t addend;
427
        int delta_timestamp;
428

    
429
        /* compute pts from timestamp with received ntp_time */
430
        delta_timestamp = timestamp - s->last_rtcp_timestamp;
431
        /* convert to the PTS timebase */
432
        addend = av_rescale(s->last_rtcp_ntp_time, s->st->time_base.den, (uint64_t)s->st->time_base.num << 32);
433
        pkt->pts = addend + delta_timestamp;
434
    }
435
}
436

    
437
/**
438
 * Parse an RTP or RTCP packet directly sent as a buffer.
439
 * @param s RTP parse context.
440
 * @param pkt returned packet
441
 * @param buf input buffer or NULL to read the next packets
442
 * @param len buffer len
443
 * @return 0 if a packet is returned, 1 if a packet is returned and more can follow
444
 * (use buf as NULL to read the next). -1 if no packet (error or no more packet).
445
 */
446
int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
447
                     const uint8_t *buf, int len)
448
{
449
    unsigned int ssrc, h;
450
    int payload_type, seq, ret, flags = 0;
451
    AVStream *st;
452
    uint32_t timestamp;
453
    int rv= 0;
454

    
455
    if (!buf) {
456
        /* return the next packets, if any */
457
        if(s->st && s->parse_packet) {
458
            timestamp= 0; ///< Should not be used if buf is NULL, but should be set to the timestamp of the packet returned....
459
            rv= s->parse_packet(s->ic, s->dynamic_protocol_context,
460
                                s->st, pkt, &timestamp, NULL, 0, flags);
461
            finalize_packet(s, pkt, timestamp);
462
            return rv;
463
        } else {
464
            // TODO: Move to a dynamic packet handler (like above)
465
            if (s->read_buf_index >= s->read_buf_size)
466
                return -1;
467
            ret = ff_mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index,
468
                                      s->read_buf_size - s->read_buf_index);
469
            if (ret < 0)
470
                return -1;
471
            s->read_buf_index += ret;
472
            if (s->read_buf_index < s->read_buf_size)
473
                return 1;
474
            else
475
                return 0;
476
        }
477
    }
478

    
479
    if (len < 12)
480
        return -1;
481

    
482
    if ((buf[0] & 0xc0) != (RTP_VERSION << 6))
483
        return -1;
484
    if (buf[1] >= 200 && buf[1] <= 204) {
485
        rtcp_parse_packet(s, buf, len);
486
        return -1;
487
    }
488
    payload_type = buf[1] & 0x7f;
489
    if (buf[1] & 0x80)
490
        flags |= RTP_FLAG_MARKER;
491
    seq  = AV_RB16(buf + 2);
492
    timestamp = AV_RB32(buf + 4);
493
    ssrc = AV_RB32(buf + 8);
494
    /* store the ssrc in the RTPDemuxContext */
495
    s->ssrc = ssrc;
496

    
497
    /* NOTE: we can handle only one payload type */
498
    if (s->payload_type != payload_type)
499
        return -1;
500

    
501
    st = s->st;
502
    // only do something with this if all the rtp checks pass...
503
    if(!rtp_valid_packet_in_sequence(&s->statistics, seq))
504
    {
505
        av_log(st?st->codec:NULL, AV_LOG_ERROR, "RTP: PT=%02x: bad cseq %04x expected=%04x\n",
506
               payload_type, seq, ((s->seq + 1) & 0xffff));
507
        return -1;
508
    }
509

    
510
    s->seq = seq;
511
    len -= 12;
512
    buf += 12;
513

    
514
    if (!st) {
515
        /* specific MPEG2TS demux support */
516
        ret = ff_mpegts_parse_packet(s->ts, pkt, buf, len);
517
        if (ret < 0)
518
            return -1;
519
        if (ret < len) {
520
            s->read_buf_size = len - ret;
521
            memcpy(s->buf, buf + ret, s->read_buf_size);
522
            s->read_buf_index = 0;
523
            return 1;
524
        }
525
        return 0;
526
    } else if (s->parse_packet) {
527
        rv = s->parse_packet(s->ic, s->dynamic_protocol_context,
528
                             s->st, pkt, &timestamp, buf, len, flags);
529
    } else {
530
        // at this point, the RTP header has been stripped;  This is ASSUMING that there is only 1 CSRC, which in't wise.
531
        switch(st->codec->codec_id) {
532
        case CODEC_ID_MP2:
533
        case CODEC_ID_MP3:
534
            /* better than nothing: skip mpeg audio RTP header */
535
            if (len <= 4)
536
                return -1;
537
            h = AV_RB32(buf);
538
            len -= 4;
539
            buf += 4;
540
            av_new_packet(pkt, len);
541
            memcpy(pkt->data, buf, len);
542
            break;
543
        case CODEC_ID_MPEG1VIDEO:
544
        case CODEC_ID_MPEG2VIDEO:
545
            /* better than nothing: skip mpeg video RTP header */
546
            if (len <= 4)
547
                return -1;
548
            h = AV_RB32(buf);
549
            buf += 4;
550
            len -= 4;
551
            if (h & (1 << 26)) {
552
                /* mpeg2 */
553
                if (len <= 4)
554
                    return -1;
555
                buf += 4;
556
                len -= 4;
557
            }
558
            av_new_packet(pkt, len);
559
            memcpy(pkt->data, buf, len);
560
            break;
561
            // moved from below, verbatim.  this is because this section handles packets, and the lower switch handles
562
            // timestamps.
563
            // TODO: Put this into a dynamic packet handler...
564
        case CODEC_ID_AAC:
565
            if (rtp_parse_mp4_au(s, buf))
566
                return -1;
567
            {
568
                RTPPayloadData *infos = s->rtp_payload_data;
569
                if (infos == NULL)
570
                    return -1;
571
                buf += infos->au_headers_length_bytes + 2;
572
                len -= infos->au_headers_length_bytes + 2;
573

    
574
                /* XXX: Fixme we only handle the case where rtp_parse_mp4_au define
575
                    one au_header */
576
                av_new_packet(pkt, infos->au_headers[0].size);
577
                memcpy(pkt->data, buf, infos->au_headers[0].size);
578
                buf += infos->au_headers[0].size;
579
                len -= infos->au_headers[0].size;
580
            }
581
            s->read_buf_size = len;
582
            rv= 0;
583
            break;
584
        default:
585
            av_new_packet(pkt, len);
586
            memcpy(pkt->data, buf, len);
587
            break;
588
        }
589

    
590
        pkt->stream_index = st->index;
591
    }
592

    
593
    // now perform timestamp things....
594
    finalize_packet(s, pkt, timestamp);
595

    
596
    return rv;
597
}
598

    
599
void rtp_parse_close(RTPDemuxContext *s)
600
{
601
    // TODO: fold this into the protocol specific data fields.
602
    if (!strcmp(ff_rtp_enc_name(s->payload_type), "MP2T")) {
603
        ff_mpegts_parse_close(s->ts);
604
    }
605
    av_free(s);
606
}