ffmpeg / libavformat / rtpdec.c @ 9106a698
History | View | Annotate | Download (18.2 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 "rtp_asf.h" |
34 |
#include "rtp_h264.h" |
35 |
|
36 |
//#define DEBUG
|
37 |
|
38 |
/* TODO: - add RTCP statistics reporting (should be optional).
|
39 |
|
40 |
- add support for h263/mpeg4 packetized output : IDEA: send a
|
41 |
buffer to 'rtp_write_packet' contains all the packets for ONE
|
42 |
frame. Each packet should have a four byte header containing
|
43 |
the length in big endian format (same trick as
|
44 |
'url_open_dyn_packet_buf')
|
45 |
*/
|
46 |
|
47 |
/* statistics functions */
|
48 |
RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler= NULL;
|
49 |
|
50 |
static RTPDynamicProtocolHandler mp4v_es_handler= {"MP4V-ES", CODEC_TYPE_VIDEO, CODEC_ID_MPEG4}; |
51 |
static RTPDynamicProtocolHandler mpeg4_generic_handler= {"mpeg4-generic", CODEC_TYPE_AUDIO, CODEC_ID_AAC}; |
52 |
|
53 |
void ff_register_dynamic_payload_handler(RTPDynamicProtocolHandler *handler)
|
54 |
{ |
55 |
handler->next= RTPFirstDynamicPayloadHandler; |
56 |
RTPFirstDynamicPayloadHandler= handler; |
57 |
} |
58 |
|
59 |
void av_register_rtp_dynamic_payload_handlers(void) |
60 |
{ |
61 |
ff_register_dynamic_payload_handler(&mp4v_es_handler); |
62 |
ff_register_dynamic_payload_handler(&mpeg4_generic_handler); |
63 |
ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler); |
64 |
|
65 |
ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler); |
66 |
ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfa_handler); |
67 |
} |
68 |
|
69 |
static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int len) |
70 |
{ |
71 |
if (buf[1] != 200) |
72 |
return -1; |
73 |
s->last_rtcp_ntp_time = AV_RB64(buf + 8);
|
74 |
if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE)
|
75 |
s->first_rtcp_ntp_time = s->last_rtcp_ntp_time; |
76 |
s->last_rtcp_timestamp = AV_RB32(buf + 16);
|
77 |
return 0; |
78 |
} |
79 |
|
80 |
#define RTP_SEQ_MOD (1<<16) |
81 |
|
82 |
/**
|
83 |
* called on parse open packet
|
84 |
*/
|
85 |
static void rtp_init_statistics(RTPStatistics *s, uint16_t base_sequence) // called on parse open packet. |
86 |
{ |
87 |
memset(s, 0, sizeof(RTPStatistics)); |
88 |
s->max_seq= base_sequence; |
89 |
s->probation= 1;
|
90 |
} |
91 |
|
92 |
/**
|
93 |
* called whenever there is a large jump in sequence numbers, or when they get out of probation...
|
94 |
*/
|
95 |
static void rtp_init_sequence(RTPStatistics *s, uint16_t seq) |
96 |
{ |
97 |
s->max_seq= seq; |
98 |
s->cycles= 0;
|
99 |
s->base_seq= seq -1;
|
100 |
s->bad_seq= RTP_SEQ_MOD + 1;
|
101 |
s->received= 0;
|
102 |
s->expected_prior= 0;
|
103 |
s->received_prior= 0;
|
104 |
s->jitter= 0;
|
105 |
s->transit= 0;
|
106 |
} |
107 |
|
108 |
/**
|
109 |
* returns 1 if we should handle this packet.
|
110 |
*/
|
111 |
static int rtp_valid_packet_in_sequence(RTPStatistics *s, uint16_t seq) |
112 |
{ |
113 |
uint16_t udelta= seq - s->max_seq; |
114 |
const int MAX_DROPOUT= 3000; |
115 |
const int MAX_MISORDER = 100; |
116 |
const int MIN_SEQUENTIAL = 2; |
117 |
|
118 |
/* source not valid until MIN_SEQUENTIAL packets with sequence seq. numbers have been received */
|
119 |
if(s->probation)
|
120 |
{ |
121 |
if(seq==s->max_seq + 1) { |
122 |
s->probation--; |
123 |
s->max_seq= seq; |
124 |
if(s->probation==0) { |
125 |
rtp_init_sequence(s, seq); |
126 |
s->received++; |
127 |
return 1; |
128 |
} |
129 |
} else {
|
130 |
s->probation= MIN_SEQUENTIAL - 1;
|
131 |
s->max_seq = seq; |
132 |
} |
133 |
} else if (udelta < MAX_DROPOUT) { |
134 |
// in order, with permissible gap
|
135 |
if(seq < s->max_seq) {
|
136 |
//sequence number wrapped; count antother 64k cycles
|
137 |
s->cycles += RTP_SEQ_MOD; |
138 |
} |
139 |
s->max_seq= seq; |
140 |
} else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) { |
141 |
// sequence made a large jump...
|
142 |
if(seq==s->bad_seq) {
|
143 |
// two sequential packets-- assume that the other side restarted without telling us; just resync.
|
144 |
rtp_init_sequence(s, seq); |
145 |
} else {
|
146 |
s->bad_seq= (seq + 1) & (RTP_SEQ_MOD-1); |
147 |
return 0; |
148 |
} |
149 |
} else {
|
150 |
// duplicate or reordered packet...
|
151 |
} |
152 |
s->received++; |
153 |
return 1; |
154 |
} |
155 |
|
156 |
#if 0
|
157 |
/**
|
158 |
* This function is currently unused; without a valid local ntp time, I don't see how we could calculate the
|
159 |
* difference between the arrival and sent timestamp. As a result, the jitter and transit statistics values
|
160 |
* never change. I left this in in case someone else can see a way. (rdm)
|
161 |
*/
|
162 |
static void rtcp_update_jitter(RTPStatistics *s, uint32_t sent_timestamp, uint32_t arrival_timestamp)
|
163 |
{
|
164 |
uint32_t transit= arrival_timestamp - sent_timestamp;
|
165 |
int d;
|
166 |
s->transit= transit;
|
167 |
d= FFABS(transit - s->transit);
|
168 |
s->jitter += d - ((s->jitter + 8)>>4);
|
169 |
}
|
170 |
#endif
|
171 |
|
172 |
int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count) |
173 |
{ |
174 |
ByteIOContext *pb; |
175 |
uint8_t *buf; |
176 |
int len;
|
177 |
int rtcp_bytes;
|
178 |
RTPStatistics *stats= &s->statistics; |
179 |
uint32_t lost; |
180 |
uint32_t extended_max; |
181 |
uint32_t expected_interval; |
182 |
uint32_t received_interval; |
183 |
uint32_t lost_interval; |
184 |
uint32_t expected; |
185 |
uint32_t fraction; |
186 |
uint64_t ntp_time= s->last_rtcp_ntp_time; // TODO: Get local ntp time?
|
187 |
|
188 |
if (!s->rtp_ctx || (count < 1)) |
189 |
return -1; |
190 |
|
191 |
/* TODO: I think this is way too often; RFC 1889 has algorithm for this */
|
192 |
/* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
|
193 |
s->octet_count += count; |
194 |
rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) / |
195 |
RTCP_TX_RATIO_DEN; |
196 |
rtcp_bytes /= 50; // mmu_man: that's enough for me... VLC sends much less btw !? |
197 |
if (rtcp_bytes < 28) |
198 |
return -1; |
199 |
s->last_octet_count = s->octet_count; |
200 |
|
201 |
if (url_open_dyn_buf(&pb) < 0) |
202 |
return -1; |
203 |
|
204 |
// Receiver Report
|
205 |
put_byte(pb, (RTP_VERSION << 6) + 1); /* 1 report block */ |
206 |
put_byte(pb, 201);
|
207 |
put_be16(pb, 7); /* length in words - 1 */ |
208 |
put_be32(pb, s->ssrc); // our own SSRC
|
209 |
put_be32(pb, s->ssrc); // XXX: should be the server's here!
|
210 |
// some placeholders we should really fill...
|
211 |
// RFC 1889/p64
|
212 |
extended_max= stats->cycles + stats->max_seq; |
213 |
expected= extended_max - stats->base_seq + 1;
|
214 |
lost= expected - stats->received; |
215 |
lost= FFMIN(lost, 0xffffff); // clamp it since it's only 24 bits... |
216 |
expected_interval= expected - stats->expected_prior; |
217 |
stats->expected_prior= expected; |
218 |
received_interval= stats->received - stats->received_prior; |
219 |
stats->received_prior= stats->received; |
220 |
lost_interval= expected_interval - received_interval; |
221 |
if (expected_interval==0 || lost_interval<=0) fraction= 0; |
222 |
else fraction = (lost_interval<<8)/expected_interval; |
223 |
|
224 |
fraction= (fraction<<24) | lost;
|
225 |
|
226 |
put_be32(pb, fraction); /* 8 bits of fraction, 24 bits of total packets lost */
|
227 |
put_be32(pb, extended_max); /* max sequence received */
|
228 |
put_be32(pb, stats->jitter>>4); /* jitter */ |
229 |
|
230 |
if(s->last_rtcp_ntp_time==AV_NOPTS_VALUE)
|
231 |
{ |
232 |
put_be32(pb, 0); /* last SR timestamp */ |
233 |
put_be32(pb, 0); /* delay since last SR */ |
234 |
} else {
|
235 |
uint32_t middle_32_bits= s->last_rtcp_ntp_time>>16; // this is valid, right? do we need to handle 64 bit values special? |
236 |
uint32_t delay_since_last= ntp_time - s->last_rtcp_ntp_time; |
237 |
|
238 |
put_be32(pb, middle_32_bits); /* last SR timestamp */
|
239 |
put_be32(pb, delay_since_last); /* delay since last SR */
|
240 |
} |
241 |
|
242 |
// CNAME
|
243 |
put_byte(pb, (RTP_VERSION << 6) + 1); /* 1 report block */ |
244 |
put_byte(pb, 202);
|
245 |
len = strlen(s->hostname); |
246 |
put_be16(pb, (6 + len + 3) / 4); /* length in words - 1 */ |
247 |
put_be32(pb, s->ssrc); |
248 |
put_byte(pb, 0x01);
|
249 |
put_byte(pb, len); |
250 |
put_buffer(pb, s->hostname, len); |
251 |
// padding
|
252 |
for (len = (6 + len) % 4; len % 4; len++) { |
253 |
put_byte(pb, 0);
|
254 |
} |
255 |
|
256 |
put_flush_packet(pb); |
257 |
len = url_close_dyn_buf(pb, &buf); |
258 |
if ((len > 0) && buf) { |
259 |
int result;
|
260 |
dprintf(s->ic, "sending %d bytes of RR\n", len);
|
261 |
result= url_write(s->rtp_ctx, buf, len); |
262 |
dprintf(s->ic, "result from url_write: %d\n", result);
|
263 |
av_free(buf); |
264 |
} |
265 |
return 0; |
266 |
} |
267 |
|
268 |
/**
|
269 |
* open a new RTP parse context for stream 'st'. 'st' can be NULL for
|
270 |
* MPEG2TS streams to indicate that they should be demuxed inside the
|
271 |
* rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned)
|
272 |
* TODO: change this to not take rtp_payload data, and use the new dynamic payload system.
|
273 |
*/
|
274 |
RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, RTPPayloadData *rtp_payload_data)
|
275 |
{ |
276 |
RTPDemuxContext *s; |
277 |
|
278 |
s = av_mallocz(sizeof(RTPDemuxContext));
|
279 |
if (!s)
|
280 |
return NULL; |
281 |
s->payload_type = payload_type; |
282 |
s->last_rtcp_ntp_time = AV_NOPTS_VALUE; |
283 |
s->first_rtcp_ntp_time = AV_NOPTS_VALUE; |
284 |
s->ic = s1; |
285 |
s->st = st; |
286 |
s->rtp_payload_data = rtp_payload_data; |
287 |
rtp_init_statistics(&s->statistics, 0); // do we know the initial sequence from sdp? |
288 |
if (!strcmp(ff_rtp_enc_name(payload_type), "MP2T")) { |
289 |
s->ts = mpegts_parse_open(s->ic); |
290 |
if (s->ts == NULL) { |
291 |
av_free(s); |
292 |
return NULL; |
293 |
} |
294 |
} else {
|
295 |
av_set_pts_info(st, 32, 1, 90000); |
296 |
switch(st->codec->codec_id) {
|
297 |
case CODEC_ID_MPEG1VIDEO:
|
298 |
case CODEC_ID_MPEG2VIDEO:
|
299 |
case CODEC_ID_MP2:
|
300 |
case CODEC_ID_MP3:
|
301 |
case CODEC_ID_MPEG4:
|
302 |
case CODEC_ID_H264:
|
303 |
st->need_parsing = AVSTREAM_PARSE_FULL; |
304 |
break;
|
305 |
default:
|
306 |
if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
|
307 |
av_set_pts_info(st, 32, 1, st->codec->sample_rate); |
308 |
} |
309 |
break;
|
310 |
} |
311 |
} |
312 |
// needed to send back RTCP RR in RTSP sessions
|
313 |
s->rtp_ctx = rtpc; |
314 |
gethostname(s->hostname, sizeof(s->hostname));
|
315 |
return s;
|
316 |
} |
317 |
|
318 |
void
|
319 |
rtp_parse_set_dynamic_protocol(RTPDemuxContext *s, PayloadContext *ctx, |
320 |
RTPDynamicProtocolHandler *handler) |
321 |
{ |
322 |
s->dynamic_protocol_context = ctx; |
323 |
s->parse_packet = handler->parse_packet; |
324 |
} |
325 |
|
326 |
static int rtp_parse_mp4_au(RTPDemuxContext *s, const uint8_t *buf) |
327 |
{ |
328 |
int au_headers_length, au_header_size, i;
|
329 |
GetBitContext getbitcontext; |
330 |
RTPPayloadData *infos; |
331 |
|
332 |
infos = s->rtp_payload_data; |
333 |
|
334 |
if (infos == NULL) |
335 |
return -1; |
336 |
|
337 |
/* decode the first 2 bytes where the AUHeader sections are stored
|
338 |
length in bits */
|
339 |
au_headers_length = AV_RB16(buf); |
340 |
|
341 |
if (au_headers_length > RTP_MAX_PACKET_LENGTH)
|
342 |
return -1; |
343 |
|
344 |
infos->au_headers_length_bytes = (au_headers_length + 7) / 8; |
345 |
|
346 |
/* skip AU headers length section (2 bytes) */
|
347 |
buf += 2;
|
348 |
|
349 |
init_get_bits(&getbitcontext, buf, infos->au_headers_length_bytes * 8);
|
350 |
|
351 |
/* XXX: Wrong if optionnal additional sections are present (cts, dts etc...) */
|
352 |
au_header_size = infos->sizelength + infos->indexlength; |
353 |
if (au_header_size <= 0 || (au_headers_length % au_header_size != 0)) |
354 |
return -1; |
355 |
|
356 |
infos->nb_au_headers = au_headers_length / au_header_size; |
357 |
infos->au_headers = av_malloc(sizeof(struct AUHeaders) * infos->nb_au_headers); |
358 |
|
359 |
/* XXX: We handle multiple AU Section as only one (need to fix this for interleaving)
|
360 |
In my test, the FAAD decoder does not behave correctly when sending each AU one by one
|
361 |
but does when sending the whole as one big packet... */
|
362 |
infos->au_headers[0].size = 0; |
363 |
infos->au_headers[0].index = 0; |
364 |
for (i = 0; i < infos->nb_au_headers; ++i) { |
365 |
infos->au_headers[0].size += get_bits_long(&getbitcontext, infos->sizelength);
|
366 |
infos->au_headers[0].index = get_bits_long(&getbitcontext, infos->indexlength);
|
367 |
} |
368 |
|
369 |
infos->nb_au_headers = 1;
|
370 |
|
371 |
return 0; |
372 |
} |
373 |
|
374 |
/**
|
375 |
* This was the second switch in rtp_parse packet. Normalizes time, if required, sets stream_index, etc.
|
376 |
*/
|
377 |
static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestamp) |
378 |
{ |
379 |
if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) {
|
380 |
int64_t addend; |
381 |
int delta_timestamp;
|
382 |
|
383 |
/* compute pts from timestamp with received ntp_time */
|
384 |
delta_timestamp = timestamp - s->last_rtcp_timestamp; |
385 |
/* convert to the PTS timebase */
|
386 |
addend = av_rescale(s->last_rtcp_ntp_time - s->first_rtcp_ntp_time, s->st->time_base.den, (uint64_t)s->st->time_base.num << 32);
|
387 |
pkt->pts = addend + delta_timestamp; |
388 |
} |
389 |
} |
390 |
|
391 |
/**
|
392 |
* Parse an RTP or RTCP packet directly sent as a buffer.
|
393 |
* @param s RTP parse context.
|
394 |
* @param pkt returned packet
|
395 |
* @param buf input buffer or NULL to read the next packets
|
396 |
* @param len buffer len
|
397 |
* @return 0 if a packet is returned, 1 if a packet is returned and more can follow
|
398 |
* (use buf as NULL to read the next). -1 if no packet (error or no more packet).
|
399 |
*/
|
400 |
int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
|
401 |
const uint8_t *buf, int len) |
402 |
{ |
403 |
unsigned int ssrc, h; |
404 |
int payload_type, seq, ret, flags = 0; |
405 |
AVStream *st; |
406 |
uint32_t timestamp; |
407 |
int rv= 0; |
408 |
|
409 |
if (!buf) {
|
410 |
/* return the next packets, if any */
|
411 |
if(s->st && s->parse_packet) {
|
412 |
timestamp= 0; ///< Should not be used if buf is NULL, but should be set to the timestamp of the packet returned.... |
413 |
rv= s->parse_packet(s->ic, s->dynamic_protocol_context, |
414 |
s->st, pkt, ×tamp, NULL, 0, flags); |
415 |
finalize_packet(s, pkt, timestamp); |
416 |
return rv;
|
417 |
} else {
|
418 |
// TODO: Move to a dynamic packet handler (like above)
|
419 |
if (s->read_buf_index >= s->read_buf_size)
|
420 |
return -1; |
421 |
ret = mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index, |
422 |
s->read_buf_size - s->read_buf_index); |
423 |
if (ret < 0) |
424 |
return -1; |
425 |
s->read_buf_index += ret; |
426 |
if (s->read_buf_index < s->read_buf_size)
|
427 |
return 1; |
428 |
else
|
429 |
return 0; |
430 |
} |
431 |
} |
432 |
|
433 |
if (len < 12) |
434 |
return -1; |
435 |
|
436 |
if ((buf[0] & 0xc0) != (RTP_VERSION << 6)) |
437 |
return -1; |
438 |
if (buf[1] >= 200 && buf[1] <= 204) { |
439 |
rtcp_parse_packet(s, buf, len); |
440 |
return -1; |
441 |
} |
442 |
payload_type = buf[1] & 0x7f; |
443 |
if (buf[1] & 0x80) |
444 |
flags |= RTP_FLAG_MARKER; |
445 |
seq = AV_RB16(buf + 2);
|
446 |
timestamp = AV_RB32(buf + 4);
|
447 |
ssrc = AV_RB32(buf + 8);
|
448 |
/* store the ssrc in the RTPDemuxContext */
|
449 |
s->ssrc = ssrc; |
450 |
|
451 |
/* NOTE: we can handle only one payload type */
|
452 |
if (s->payload_type != payload_type)
|
453 |
return -1; |
454 |
|
455 |
st = s->st; |
456 |
// only do something with this if all the rtp checks pass...
|
457 |
if(!rtp_valid_packet_in_sequence(&s->statistics, seq))
|
458 |
{ |
459 |
av_log(st?st->codec:NULL, AV_LOG_ERROR, "RTP: PT=%02x: bad cseq %04x expected=%04x\n", |
460 |
payload_type, seq, ((s->seq + 1) & 0xffff)); |
461 |
return -1; |
462 |
} |
463 |
|
464 |
s->seq = seq; |
465 |
len -= 12;
|
466 |
buf += 12;
|
467 |
|
468 |
if (!st) {
|
469 |
/* specific MPEG2TS demux support */
|
470 |
ret = mpegts_parse_packet(s->ts, pkt, buf, len); |
471 |
if (ret < 0) |
472 |
return -1; |
473 |
if (ret < len) {
|
474 |
s->read_buf_size = len - ret; |
475 |
memcpy(s->buf, buf + ret, s->read_buf_size); |
476 |
s->read_buf_index = 0;
|
477 |
return 1; |
478 |
} |
479 |
return 0; |
480 |
} else if (s->parse_packet) { |
481 |
rv = s->parse_packet(s->ic, s->dynamic_protocol_context, |
482 |
s->st, pkt, ×tamp, buf, len, flags); |
483 |
} else {
|
484 |
// at this point, the RTP header has been stripped; This is ASSUMING that there is only 1 CSRC, which in't wise.
|
485 |
switch(st->codec->codec_id) {
|
486 |
case CODEC_ID_MP2:
|
487 |
/* better than nothing: skip mpeg audio RTP header */
|
488 |
if (len <= 4) |
489 |
return -1; |
490 |
h = AV_RB32(buf); |
491 |
len -= 4;
|
492 |
buf += 4;
|
493 |
av_new_packet(pkt, len); |
494 |
memcpy(pkt->data, buf, len); |
495 |
break;
|
496 |
case CODEC_ID_MPEG1VIDEO:
|
497 |
case CODEC_ID_MPEG2VIDEO:
|
498 |
/* better than nothing: skip mpeg video RTP header */
|
499 |
if (len <= 4) |
500 |
return -1; |
501 |
h = AV_RB32(buf); |
502 |
buf += 4;
|
503 |
len -= 4;
|
504 |
if (h & (1 << 26)) { |
505 |
/* mpeg2 */
|
506 |
if (len <= 4) |
507 |
return -1; |
508 |
buf += 4;
|
509 |
len -= 4;
|
510 |
} |
511 |
av_new_packet(pkt, len); |
512 |
memcpy(pkt->data, buf, len); |
513 |
break;
|
514 |
// moved from below, verbatim. this is because this section handles packets, and the lower switch handles
|
515 |
// timestamps.
|
516 |
// TODO: Put this into a dynamic packet handler...
|
517 |
case CODEC_ID_AAC:
|
518 |
if (rtp_parse_mp4_au(s, buf))
|
519 |
return -1; |
520 |
{ |
521 |
RTPPayloadData *infos = s->rtp_payload_data; |
522 |
if (infos == NULL) |
523 |
return -1; |
524 |
buf += infos->au_headers_length_bytes + 2;
|
525 |
len -= infos->au_headers_length_bytes + 2;
|
526 |
|
527 |
/* XXX: Fixme we only handle the case where rtp_parse_mp4_au define
|
528 |
one au_header */
|
529 |
av_new_packet(pkt, infos->au_headers[0].size);
|
530 |
memcpy(pkt->data, buf, infos->au_headers[0].size);
|
531 |
buf += infos->au_headers[0].size;
|
532 |
len -= infos->au_headers[0].size;
|
533 |
} |
534 |
s->read_buf_size = len; |
535 |
rv= 0;
|
536 |
break;
|
537 |
default:
|
538 |
av_new_packet(pkt, len); |
539 |
memcpy(pkt->data, buf, len); |
540 |
break;
|
541 |
} |
542 |
|
543 |
pkt->stream_index = st->index; |
544 |
} |
545 |
|
546 |
// now perform timestamp things....
|
547 |
finalize_packet(s, pkt, timestamp); |
548 |
|
549 |
return rv;
|
550 |
} |
551 |
|
552 |
void rtp_parse_close(RTPDemuxContext *s)
|
553 |
{ |
554 |
// TODO: fold this into the protocol specific data fields.
|
555 |
if (!strcmp(ff_rtp_enc_name(s->payload_type), "MP2T")) { |
556 |
mpegts_parse_close(s->ts); |
557 |
} |
558 |
av_free(s); |
559 |
} |