remove empty write trailer functions
[libav.git] / libavformat / rtp.c
1 /*
2 * RTP input/output 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 #include "avformat.h"
22 #include "mpegts.h"
23 #include "bitstream.h"
24
25 #include <unistd.h>
26 #include "network.h"
27
28 #include "rtp_internal.h"
29 #include "rtp_h264.h"
30
31 //#define DEBUG
32
33
34 /* TODO: - add RTCP statistics reporting (should be optional).
35
36 - add support for h263/mpeg4 packetized output : IDEA: send a
37 buffer to 'rtp_write_packet' contains all the packets for ONE
38 frame. Each packet should have a four byte header containing
39 the length in big endian format (same trick as
40 'url_open_dyn_packet_buf')
41 */
42
43 /* from http://www.iana.org/assignments/rtp-parameters last updated 05 January 2005 */
44 AVRtpPayloadType_t AVRtpPayloadTypes[]=
45 {
46 {0, "PCMU", CODEC_TYPE_AUDIO, CODEC_ID_PCM_MULAW, 8000, 1},
47 {1, "Reserved", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
48 {2, "Reserved", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
49 {3, "GSM", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
50 {4, "G723", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
51 {5, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
52 {6, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 16000, 1},
53 {7, "LPC", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
54 {8, "PCMA", CODEC_TYPE_AUDIO, CODEC_ID_PCM_ALAW, 8000, 1},
55 {9, "G722", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
56 {10, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 2},
57 {11, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 1},
58 {12, "QCELP", CODEC_TYPE_AUDIO, CODEC_ID_QCELP, 8000, 1},
59 {13, "CN", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
60 {14, "MPA", CODEC_TYPE_AUDIO, CODEC_ID_MP2, 90000, -1},
61 {15, "G728", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
62 {16, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 11025, 1},
63 {17, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 22050, 1},
64 {18, "G729", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
65 {19, "reserved", CODEC_TYPE_AUDIO, CODEC_ID_NONE, -1, -1},
66 {20, "unassigned", CODEC_TYPE_AUDIO, CODEC_ID_NONE, -1, -1},
67 {21, "unassigned", CODEC_TYPE_AUDIO, CODEC_ID_NONE, -1, -1},
68 {22, "unassigned", CODEC_TYPE_AUDIO, CODEC_ID_NONE, -1, -1},
69 {23, "unassigned", CODEC_TYPE_AUDIO, CODEC_ID_NONE, -1, -1},
70 {24, "unassigned", CODEC_TYPE_VIDEO, CODEC_ID_NONE, -1, -1},
71 {25, "CelB", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1},
72 {26, "JPEG", CODEC_TYPE_VIDEO, CODEC_ID_MJPEG, 90000, -1},
73 {27, "unassigned", CODEC_TYPE_VIDEO, CODEC_ID_NONE, -1, -1},
74 {28, "nv", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1},
75 {29, "unassigned", CODEC_TYPE_VIDEO, CODEC_ID_NONE, -1, -1},
76 {30, "unassigned", CODEC_TYPE_VIDEO, CODEC_ID_NONE, -1, -1},
77 {31, "H261", CODEC_TYPE_VIDEO, CODEC_ID_H261, 90000, -1},
78 {32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG1VIDEO, 90000, -1},
79 {33, "MP2T", CODEC_TYPE_DATA, CODEC_ID_MPEG2TS, 90000, -1},
80 {34, "H263", CODEC_TYPE_VIDEO, CODEC_ID_H263, 90000, -1},
81 {35, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
82 {36, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
83 {37, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
84 {38, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
85 {39, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
86 {40, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
87 {41, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
88 {42, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
89 {43, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
90 {44, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
91 {45, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
92 {46, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
93 {47, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
94 {48, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
95 {49, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
96 {50, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
97 {51, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
98 {52, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
99 {53, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
100 {54, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
101 {55, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
102 {56, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
103 {57, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
104 {58, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
105 {59, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
106 {60, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
107 {61, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
108 {62, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
109 {63, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
110 {64, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
111 {65, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
112 {66, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
113 {67, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
114 {68, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
115 {69, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
116 {70, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
117 {71, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
118 {72, "reserved for RTCP conflict avoidance", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
119 {73, "reserved for RTCP conflict avoidance", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
120 {74, "reserved for RTCP conflict avoidance", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
121 {75, "reserved for RTCP conflict avoidance", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
122 {76, "reserved for RTCP conflict avoidance", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
123 {77, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
124 {78, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
125 {79, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
126 {80, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
127 {81, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
128 {82, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
129 {83, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
130 {84, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
131 {85, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
132 {86, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
133 {87, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
134 {88, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
135 {89, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
136 {90, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
137 {91, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
138 {92, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
139 {93, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
140 {94, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
141 {95, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
142 {96, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
143 {97, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
144 {98, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
145 {99, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
146 {100, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
147 {101, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
148 {102, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
149 {103, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
150 {104, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
151 {105, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
152 {106, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
153 {107, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
154 {108, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
155 {109, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
156 {110, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
157 {111, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
158 {112, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
159 {113, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
160 {114, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
161 {115, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
162 {116, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
163 {117, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
164 {118, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
165 {119, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
166 {120, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
167 {121, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
168 {122, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
169 {123, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
170 {124, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
171 {125, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
172 {126, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
173 {127, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
174 {-1, "", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1}
175 };
176
177 /* statistics functions */
178 RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler= NULL;
179
180 static RTPDynamicProtocolHandler mp4v_es_handler= {"MP4V-ES", CODEC_TYPE_VIDEO, CODEC_ID_MPEG4};
181 static RTPDynamicProtocolHandler mpeg4_generic_handler= {"mpeg4-generic", CODEC_TYPE_AUDIO, CODEC_ID_AAC};
182
183 static void register_dynamic_payload_handler(RTPDynamicProtocolHandler *handler)
184 {
185 handler->next= RTPFirstDynamicPayloadHandler;
186 RTPFirstDynamicPayloadHandler= handler;
187 }
188
189 void av_register_rtp_dynamic_payload_handlers(void)
190 {
191 register_dynamic_payload_handler(&mp4v_es_handler);
192 register_dynamic_payload_handler(&mpeg4_generic_handler);
193 register_dynamic_payload_handler(&ff_h264_dynamic_handler);
194 }
195
196 int rtp_get_codec_info(AVCodecContext *codec, int payload_type)
197 {
198 if (AVRtpPayloadTypes[payload_type].codec_id != CODEC_ID_NONE) {
199 codec->codec_type = AVRtpPayloadTypes[payload_type].codec_type;
200 codec->codec_id = AVRtpPayloadTypes[payload_type].codec_id;
201 if (AVRtpPayloadTypes[payload_type].audio_channels > 0)
202 codec->channels = AVRtpPayloadTypes[payload_type].audio_channels;
203 if (AVRtpPayloadTypes[payload_type].clock_rate > 0)
204 codec->sample_rate = AVRtpPayloadTypes[payload_type].clock_rate;
205 return 0;
206 }
207 return -1;
208 }
209
210 int rtp_get_payload_type(AVCodecContext *codec)
211 {
212 int i, payload_type;
213
214 /* compute the payload type */
215 for (payload_type = -1, i = 0; AVRtpPayloadTypes[i].pt >= 0; ++i)
216 if (AVRtpPayloadTypes[i].codec_id == codec->codec_id) {
217 if (codec->codec_id == CODEC_ID_PCM_S16BE)
218 if (codec->channels != AVRtpPayloadTypes[i].audio_channels)
219 continue;
220 payload_type = AVRtpPayloadTypes[i].pt;
221 }
222 return payload_type;
223 }
224
225 static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int len)
226 {
227 if (buf[1] != 200)
228 return -1;
229 s->last_rtcp_ntp_time = AV_RB64(buf + 8);
230 if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE)
231 s->first_rtcp_ntp_time = s->last_rtcp_ntp_time;
232 s->last_rtcp_timestamp = AV_RB32(buf + 16);
233 return 0;
234 }
235
236 #define RTP_SEQ_MOD (1<<16)
237
238 /**
239 * called on parse open packet
240 */
241 static void rtp_init_statistics(RTPStatistics *s, uint16_t base_sequence) // called on parse open packet.
242 {
243 memset(s, 0, sizeof(RTPStatistics));
244 s->max_seq= base_sequence;
245 s->probation= 1;
246 }
247
248 /**
249 * called whenever there is a large jump in sequence numbers, or when they get out of probation...
250 */
251 static void rtp_init_sequence(RTPStatistics *s, uint16_t seq)
252 {
253 s->max_seq= seq;
254 s->cycles= 0;
255 s->base_seq= seq -1;
256 s->bad_seq= RTP_SEQ_MOD + 1;
257 s->received= 0;
258 s->expected_prior= 0;
259 s->received_prior= 0;
260 s->jitter= 0;
261 s->transit= 0;
262 }
263
264 /**
265 * returns 1 if we should handle this packet.
266 */
267 static int rtp_valid_packet_in_sequence(RTPStatistics *s, uint16_t seq)
268 {
269 uint16_t udelta= seq - s->max_seq;
270 const int MAX_DROPOUT= 3000;
271 const int MAX_MISORDER = 100;
272 const int MIN_SEQUENTIAL = 2;
273
274 /* source not valid until MIN_SEQUENTIAL packets with sequence seq. numbers have been received */
275 if(s->probation)
276 {
277 if(seq==s->max_seq + 1) {
278 s->probation--;
279 s->max_seq= seq;
280 if(s->probation==0) {
281 rtp_init_sequence(s, seq);
282 s->received++;
283 return 1;
284 }
285 } else {
286 s->probation= MIN_SEQUENTIAL - 1;
287 s->max_seq = seq;
288 }
289 } else if (udelta < MAX_DROPOUT) {
290 // in order, with permissible gap
291 if(seq < s->max_seq) {
292 //sequence number wrapped; count antother 64k cycles
293 s->cycles += RTP_SEQ_MOD;
294 }
295 s->max_seq= seq;
296 } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
297 // sequence made a large jump...
298 if(seq==s->bad_seq) {
299 // two sequential packets-- assume that the other side restarted without telling us; just resync.
300 rtp_init_sequence(s, seq);
301 } else {
302 s->bad_seq= (seq + 1) & (RTP_SEQ_MOD-1);
303 return 0;
304 }
305 } else {
306 // duplicate or reordered packet...
307 }
308 s->received++;
309 return 1;
310 }
311
312 #if 0
313 /**
314 * This function is currently unused; without a valid local ntp time, I don't see how we could calculate the
315 * difference between the arrival and sent timestamp. As a result, the jitter and transit statistics values
316 * never change. I left this in in case someone else can see a way. (rdm)
317 */
318 static void rtcp_update_jitter(RTPStatistics *s, uint32_t sent_timestamp, uint32_t arrival_timestamp)
319 {
320 uint32_t transit= arrival_timestamp - sent_timestamp;
321 int d;
322 s->transit= transit;
323 d= FFABS(transit - s->transit);
324 s->jitter += d - ((s->jitter + 8)>>4);
325 }
326 #endif
327
328 int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count)
329 {
330 ByteIOContext pb;
331 uint8_t *buf;
332 int len;
333 int rtcp_bytes;
334 RTPStatistics *stats= &s->statistics;
335 uint32_t lost;
336 uint32_t extended_max;
337 uint32_t expected_interval;
338 uint32_t received_interval;
339 uint32_t lost_interval;
340 uint32_t expected;
341 uint32_t fraction;
342 uint64_t ntp_time= s->last_rtcp_ntp_time; // TODO: Get local ntp time?
343
344 if (!s->rtp_ctx || (count < 1))
345 return -1;
346
347 /* TODO: I think this is way too often; RFC 1889 has algorithm for this */
348 /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
349 s->octet_count += count;
350 rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) /
351 RTCP_TX_RATIO_DEN;
352 rtcp_bytes /= 50; // mmu_man: that's enough for me... VLC sends much less btw !?
353 if (rtcp_bytes < 28)
354 return -1;
355 s->last_octet_count = s->octet_count;
356
357 if (url_open_dyn_buf(&pb) < 0)
358 return -1;
359
360 // Receiver Report
361 put_byte(&pb, (RTP_VERSION << 6) + 1); /* 1 report block */
362 put_byte(&pb, 201);
363 put_be16(&pb, 7); /* length in words - 1 */
364 put_be32(&pb, s->ssrc); // our own SSRC
365 put_be32(&pb, s->ssrc); // XXX: should be the server's here!
366 // some placeholders we should really fill...
367 // RFC 1889/p64
368 extended_max= stats->cycles + stats->max_seq;
369 expected= extended_max - stats->base_seq + 1;
370 lost= expected - stats->received;
371 lost= FFMIN(lost, 0xffffff); // clamp it since it's only 24 bits...
372 expected_interval= expected - stats->expected_prior;
373 stats->expected_prior= expected;
374 received_interval= stats->received - stats->received_prior;
375 stats->received_prior= stats->received;
376 lost_interval= expected_interval - received_interval;
377 if (expected_interval==0 || lost_interval<=0) fraction= 0;
378 else fraction = (lost_interval<<8)/expected_interval;
379
380 fraction= (fraction<<24) | lost;
381
382 put_be32(&pb, fraction); /* 8 bits of fraction, 24 bits of total packets lost */
383 put_be32(&pb, extended_max); /* max sequence received */
384 put_be32(&pb, stats->jitter>>4); /* jitter */
385
386 if(s->last_rtcp_ntp_time==AV_NOPTS_VALUE)
387 {
388 put_be32(&pb, 0); /* last SR timestamp */
389 put_be32(&pb, 0); /* delay since last SR */
390 } else {
391 uint32_t middle_32_bits= s->last_rtcp_ntp_time>>16; // this is valid, right? do we need to handle 64 bit values special?
392 uint32_t delay_since_last= ntp_time - s->last_rtcp_ntp_time;
393
394 put_be32(&pb, middle_32_bits); /* last SR timestamp */
395 put_be32(&pb, delay_since_last); /* delay since last SR */
396 }
397
398 // CNAME
399 put_byte(&pb, (RTP_VERSION << 6) + 1); /* 1 report block */
400 put_byte(&pb, 202);
401 len = strlen(s->hostname);
402 put_be16(&pb, (6 + len + 3) / 4); /* length in words - 1 */
403 put_be32(&pb, s->ssrc);
404 put_byte(&pb, 0x01);
405 put_byte(&pb, len);
406 put_buffer(&pb, s->hostname, len);
407 // padding
408 for (len = (6 + len) % 4; len % 4; len++) {
409 put_byte(&pb, 0);
410 }
411
412 put_flush_packet(&pb);
413 len = url_close_dyn_buf(&pb, &buf);
414 if ((len > 0) && buf) {
415 int result;
416 #if defined(DEBUG)
417 printf("sending %d bytes of RR\n", len);
418 #endif
419 result= url_write(s->rtp_ctx, buf, len);
420 #if defined(DEBUG)
421 printf("result from url_write: %d\n", result);
422 #endif
423 av_free(buf);
424 }
425 return 0;
426 }
427
428 /**
429 * open a new RTP parse context for stream 'st'. 'st' can be NULL for
430 * MPEG2TS streams to indicate that they should be demuxed inside the
431 * rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned)
432 * TODO: change this to not take rtp_payload data, and use the new dynamic payload system.
433 */
434 RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, rtp_payload_data_t *rtp_payload_data)
435 {
436 RTPDemuxContext *s;
437
438 s = av_mallocz(sizeof(RTPDemuxContext));
439 if (!s)
440 return NULL;
441 s->payload_type = payload_type;
442 s->last_rtcp_ntp_time = AV_NOPTS_VALUE;
443 s->first_rtcp_ntp_time = AV_NOPTS_VALUE;
444 s->ic = s1;
445 s->st = st;
446 s->rtp_payload_data = rtp_payload_data;
447 rtp_init_statistics(&s->statistics, 0); // do we know the initial sequence from sdp?
448 if (!strcmp(AVRtpPayloadTypes[payload_type].enc_name, "MP2T")) {
449 s->ts = mpegts_parse_open(s->ic);
450 if (s->ts == NULL) {
451 av_free(s);
452 return NULL;
453 }
454 } else {
455 switch(st->codec->codec_id) {
456 case CODEC_ID_MPEG1VIDEO:
457 case CODEC_ID_MPEG2VIDEO:
458 case CODEC_ID_MP2:
459 case CODEC_ID_MP3:
460 case CODEC_ID_MPEG4:
461 case CODEC_ID_H264:
462 st->need_parsing = AVSTREAM_PARSE_FULL;
463 break;
464 default:
465 break;
466 }
467 }
468 // needed to send back RTCP RR in RTSP sessions
469 s->rtp_ctx = rtpc;
470 gethostname(s->hostname, sizeof(s->hostname));
471 return s;
472 }
473
474 static int rtp_parse_mp4_au(RTPDemuxContext *s, const uint8_t *buf)
475 {
476 int au_headers_length, au_header_size, i;
477 GetBitContext getbitcontext;
478 rtp_payload_data_t *infos;
479
480 infos = s->rtp_payload_data;
481
482 if (infos == NULL)
483 return -1;
484
485 /* decode the first 2 bytes where are stored the AUHeader sections
486 length in bits */
487 au_headers_length = AV_RB16(buf);
488
489 if (au_headers_length > RTP_MAX_PACKET_LENGTH)
490 return -1;
491
492 infos->au_headers_length_bytes = (au_headers_length + 7) / 8;
493
494 /* skip AU headers length section (2 bytes) */
495 buf += 2;
496
497 init_get_bits(&getbitcontext, buf, infos->au_headers_length_bytes * 8);
498
499 /* XXX: Wrong if optionnal additional sections are present (cts, dts etc...) */
500 au_header_size = infos->sizelength + infos->indexlength;
501 if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
502 return -1;
503
504 infos->nb_au_headers = au_headers_length / au_header_size;
505 infos->au_headers = av_malloc(sizeof(struct AUHeaders) * infos->nb_au_headers);
506
507 /* XXX: We handle multiple AU Section as only one (need to fix this for interleaving)
508 In my test, the FAAD decoder does not behave correctly when sending each AU one by one
509 but does when sending the whole as one big packet... */
510 infos->au_headers[0].size = 0;
511 infos->au_headers[0].index = 0;
512 for (i = 0; i < infos->nb_au_headers; ++i) {
513 infos->au_headers[0].size += get_bits_long(&getbitcontext, infos->sizelength);
514 infos->au_headers[0].index = get_bits_long(&getbitcontext, infos->indexlength);
515 }
516
517 infos->nb_au_headers = 1;
518
519 return 0;
520 }
521
522 /**
523 * This was the second switch in rtp_parse packet. Normalizes time, if required, sets stream_index, etc.
524 */
525 static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestamp)
526 {
527 switch(s->st->codec->codec_id) {
528 case CODEC_ID_MP2:
529 case CODEC_ID_MPEG1VIDEO:
530 if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) {
531 int64_t addend;
532
533 int delta_timestamp;
534 /* XXX: is it really necessary to unify the timestamp base ? */
535 /* compute pts from timestamp with received ntp_time */
536 delta_timestamp = timestamp - s->last_rtcp_timestamp;
537 /* convert to 90 kHz without overflow */
538 addend = (s->last_rtcp_ntp_time - s->first_rtcp_ntp_time) >> 14;
539 addend = (addend * 5625) >> 14;
540 pkt->pts = addend + delta_timestamp;
541 }
542 break;
543 case CODEC_ID_AAC:
544 case CODEC_ID_H264:
545 case CODEC_ID_MPEG4:
546 pkt->pts = timestamp;
547 break;
548 default:
549 /* no timestamp info yet */
550 break;
551 }
552 pkt->stream_index = s->st->index;
553 }
554
555 /**
556 * Parse an RTP or RTCP packet directly sent as a buffer.
557 * @param s RTP parse context.
558 * @param pkt returned packet
559 * @param buf input buffer or NULL to read the next packets
560 * @param len buffer len
561 * @return 0 if a packet is returned, 1 if a packet is returned and more can follow
562 * (use buf as NULL to read the next). -1 if no packet (error or no more packet).
563 */
564 int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
565 const uint8_t *buf, int len)
566 {
567 unsigned int ssrc, h;
568 int payload_type, seq, ret;
569 AVStream *st;
570 uint32_t timestamp;
571 int rv= 0;
572
573 if (!buf) {
574 /* return the next packets, if any */
575 if(s->st && s->parse_packet) {
576 timestamp= 0; ///< Should not be used if buf is NULL, but should be set to the timestamp of the packet returned....
577 rv= s->parse_packet(s, pkt, &timestamp, NULL, 0);
578 finalize_packet(s, pkt, timestamp);
579 return rv;
580 } else {
581 // TODO: Move to a dynamic packet handler (like above)
582 if (s->read_buf_index >= s->read_buf_size)
583 return -1;
584 ret = mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index,
585 s->read_buf_size - s->read_buf_index);
586 if (ret < 0)
587 return -1;
588 s->read_buf_index += ret;
589 if (s->read_buf_index < s->read_buf_size)
590 return 1;
591 else
592 return 0;
593 }
594 }
595
596 if (len < 12)
597 return -1;
598
599 if ((buf[0] & 0xc0) != (RTP_VERSION << 6))
600 return -1;
601 if (buf[1] >= 200 && buf[1] <= 204) {
602 rtcp_parse_packet(s, buf, len);
603 return -1;
604 }
605 payload_type = buf[1] & 0x7f;
606 seq = (buf[2] << 8) | buf[3];
607 timestamp = AV_RB32(buf + 4);
608 ssrc = AV_RB32(buf + 8);
609 /* store the ssrc in the RTPDemuxContext */
610 s->ssrc = ssrc;
611
612 /* NOTE: we can handle only one payload type */
613 if (s->payload_type != payload_type)
614 return -1;
615
616 st = s->st;
617 // only do something with this if all the rtp checks pass...
618 if(!rtp_valid_packet_in_sequence(&s->statistics, seq))
619 {
620 av_log(st?st->codec:NULL, AV_LOG_ERROR, "RTP: PT=%02x: bad cseq %04x expected=%04x\n",
621 payload_type, seq, ((s->seq + 1) & 0xffff));
622 return -1;
623 }
624
625 s->seq = seq;
626 len -= 12;
627 buf += 12;
628
629 if (!st) {
630 /* specific MPEG2TS demux support */
631 ret = mpegts_parse_packet(s->ts, pkt, buf, len);
632 if (ret < 0)
633 return -1;
634 if (ret < len) {
635 s->read_buf_size = len - ret;
636 memcpy(s->buf, buf + ret, s->read_buf_size);
637 s->read_buf_index = 0;
638 return 1;
639 }
640 } else {
641 // at this point, the RTP header has been stripped; This is ASSUMING that there is only 1 CSRC, which in't wise.
642 switch(st->codec->codec_id) {
643 case CODEC_ID_MP2:
644 /* better than nothing: skip mpeg audio RTP header */
645 if (len <= 4)
646 return -1;
647 h = AV_RB32(buf);
648 len -= 4;
649 buf += 4;
650 av_new_packet(pkt, len);
651 memcpy(pkt->data, buf, len);
652 break;
653 case CODEC_ID_MPEG1VIDEO:
654 /* better than nothing: skip mpeg video RTP header */
655 if (len <= 4)
656 return -1;
657 h = AV_RB32(buf);
658 buf += 4;
659 len -= 4;
660 if (h & (1 << 26)) {
661 /* mpeg2 */
662 if (len <= 4)
663 return -1;
664 buf += 4;
665 len -= 4;
666 }
667 av_new_packet(pkt, len);
668 memcpy(pkt->data, buf, len);
669 break;
670 // moved from below, verbatim. this is because this section handles packets, and the lower switch handles
671 // timestamps.
672 // TODO: Put this into a dynamic packet handler...
673 case CODEC_ID_AAC:
674 if (rtp_parse_mp4_au(s, buf))
675 return -1;
676 {
677 rtp_payload_data_t *infos = s->rtp_payload_data;
678 if (infos == NULL)
679 return -1;
680 buf += infos->au_headers_length_bytes + 2;
681 len -= infos->au_headers_length_bytes + 2;
682
683 /* XXX: Fixme we only handle the case where rtp_parse_mp4_au define
684 one au_header */
685 av_new_packet(pkt, infos->au_headers[0].size);
686 memcpy(pkt->data, buf, infos->au_headers[0].size);
687 buf += infos->au_headers[0].size;
688 len -= infos->au_headers[0].size;
689 }
690 s->read_buf_size = len;
691 s->buf_ptr = buf;
692 rv= 0;
693 break;
694 default:
695 if(s->parse_packet) {
696 rv= s->parse_packet(s, pkt, &timestamp, buf, len);
697 } else {
698 av_new_packet(pkt, len);
699 memcpy(pkt->data, buf, len);
700 }
701 break;
702 }
703
704 // now perform timestamp things....
705 finalize_packet(s, pkt, timestamp);
706 }
707 return rv;
708 }
709
710 void rtp_parse_close(RTPDemuxContext *s)
711 {
712 // TODO: fold this into the protocol specific data fields.
713 if (!strcmp(AVRtpPayloadTypes[s->payload_type].enc_name, "MP2T")) {
714 mpegts_parse_close(s->ts);
715 }
716 av_free(s);
717 }
718
719 /* rtp output */
720
721 static int rtp_write_header(AVFormatContext *s1)
722 {
723 RTPDemuxContext *s = s1->priv_data;
724 int payload_type, max_packet_size, n;
725 AVStream *st;
726
727 if (s1->nb_streams != 1)
728 return -1;
729 st = s1->streams[0];
730
731 payload_type = rtp_get_payload_type(st->codec);
732 if (payload_type < 0)
733 payload_type = RTP_PT_PRIVATE; /* private payload type */
734 s->payload_type = payload_type;
735
736 // following 2 FIXMies could be set based on the current time, theres normaly no info leak, as rtp will likely be transmitted immedeatly
737 s->base_timestamp = 0; /* FIXME: was random(), what should this be? */
738 s->timestamp = s->base_timestamp;
739 s->ssrc = 0; /* FIXME: was random(), what should this be? */
740 s->first_packet = 1;
741
742 max_packet_size = url_fget_max_packet_size(&s1->pb);
743 if (max_packet_size <= 12)
744 return AVERROR_IO;
745 s->max_payload_size = max_packet_size - 12;
746
747 switch(st->codec->codec_id) {
748 case CODEC_ID_MP2:
749 case CODEC_ID_MP3:
750 s->buf_ptr = s->buf + 4;
751 s->cur_timestamp = 0;
752 break;
753 case CODEC_ID_MPEG1VIDEO:
754 s->cur_timestamp = 0;
755 break;
756 case CODEC_ID_MPEG2TS:
757 n = s->max_payload_size / TS_PACKET_SIZE;
758 if (n < 1)
759 n = 1;
760 s->max_payload_size = n * TS_PACKET_SIZE;
761 s->buf_ptr = s->buf;
762 break;
763 default:
764 s->buf_ptr = s->buf;
765 break;
766 }
767
768 return 0;
769 }
770
771 /* send an rtcp sender report packet */
772 static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time)
773 {
774 RTPDemuxContext *s = s1->priv_data;
775 #if defined(DEBUG)
776 printf("RTCP: %02x %"PRIx64" %x\n", s->payload_type, ntp_time, s->timestamp);
777 #endif
778 put_byte(&s1->pb, (RTP_VERSION << 6));
779 put_byte(&s1->pb, 200);
780 put_be16(&s1->pb, 6); /* length in words - 1 */
781 put_be32(&s1->pb, s->ssrc);
782 put_be64(&s1->pb, ntp_time);
783 put_be32(&s1->pb, s->timestamp);
784 put_be32(&s1->pb, s->packet_count);
785 put_be32(&s1->pb, s->octet_count);
786 put_flush_packet(&s1->pb);
787 }
788
789 /* send an rtp packet. sequence number is incremented, but the caller
790 must update the timestamp itself */
791 static void rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m)
792 {
793 RTPDemuxContext *s = s1->priv_data;
794
795 #ifdef DEBUG
796 printf("rtp_send_data size=%d\n", len);
797 #endif
798
799 /* build the RTP header */
800 put_byte(&s1->pb, (RTP_VERSION << 6));
801 put_byte(&s1->pb, (s->payload_type & 0x7f) | ((m & 0x01) << 7));
802 put_be16(&s1->pb, s->seq);
803 put_be32(&s1->pb, s->timestamp);
804 put_be32(&s1->pb, s->ssrc);
805
806 put_buffer(&s1->pb, buf1, len);
807 put_flush_packet(&s1->pb);
808
809 s->seq++;
810 s->octet_count += len;
811 s->packet_count++;
812 }
813
814 /* send an integer number of samples and compute time stamp and fill
815 the rtp send buffer before sending. */
816 static void rtp_send_samples(AVFormatContext *s1,
817 const uint8_t *buf1, int size, int sample_size)
818 {
819 RTPDemuxContext *s = s1->priv_data;
820 int len, max_packet_size, n;
821
822 max_packet_size = (s->max_payload_size / sample_size) * sample_size;
823 /* not needed, but who nows */
824 if ((size % sample_size) != 0)
825 av_abort();
826 while (size > 0) {
827 len = (max_packet_size - (s->buf_ptr - s->buf));
828 if (len > size)
829 len = size;
830
831 /* copy data */
832 memcpy(s->buf_ptr, buf1, len);
833 s->buf_ptr += len;
834 buf1 += len;
835 size -= len;
836 n = (s->buf_ptr - s->buf);
837 /* if buffer full, then send it */
838 if (n >= max_packet_size) {
839 rtp_send_data(s1, s->buf, n, 0);
840 s->buf_ptr = s->buf;
841 /* update timestamp */
842 s->timestamp += n / sample_size;
843 }
844 }
845 }
846
847 /* NOTE: we suppose that exactly one frame is given as argument here */
848 /* XXX: test it */
849 static void rtp_send_mpegaudio(AVFormatContext *s1,
850 const uint8_t *buf1, int size)
851 {
852 RTPDemuxContext *s = s1->priv_data;
853 AVStream *st = s1->streams[0];
854 int len, count, max_packet_size;
855
856 max_packet_size = s->max_payload_size;
857
858 /* test if we must flush because not enough space */
859 len = (s->buf_ptr - s->buf);
860 if ((len + size) > max_packet_size) {
861 if (len > 4) {
862 rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0);
863 s->buf_ptr = s->buf + 4;
864 /* 90 KHz time stamp */
865 s->timestamp = s->base_timestamp +
866 (s->cur_timestamp * 90000LL) / st->codec->sample_rate;
867 }
868 }
869
870 /* add the packet */
871 if (size > max_packet_size) {
872 /* big packet: fragment */
873 count = 0;
874 while (size > 0) {
875 len = max_packet_size - 4;
876 if (len > size)
877 len = size;
878 /* build fragmented packet */
879 s->buf[0] = 0;
880 s->buf[1] = 0;
881 s->buf[2] = count >> 8;
882 s->buf[3] = count;
883 memcpy(s->buf + 4, buf1, len);
884 rtp_send_data(s1, s->buf, len + 4, 0);
885 size -= len;
886 buf1 += len;
887 count += len;
888 }
889 } else {
890 if (s->buf_ptr == s->buf + 4) {
891 /* no fragmentation possible */
892 s->buf[0] = 0;
893 s->buf[1] = 0;
894 s->buf[2] = 0;
895 s->buf[3] = 0;
896 }
897 memcpy(s->buf_ptr, buf1, size);
898 s->buf_ptr += size;
899 }
900 s->cur_timestamp += st->codec->frame_size;
901 }
902
903 /* NOTE: a single frame must be passed with sequence header if
904 needed. XXX: use slices. */
905 static void rtp_send_mpegvideo(AVFormatContext *s1,
906 const uint8_t *buf1, int size)
907 {
908 RTPDemuxContext *s = s1->priv_data;
909 AVStream *st = s1->streams[0];
910 int len, h, max_packet_size;
911 uint8_t *q;
912
913 max_packet_size = s->max_payload_size;
914
915 while (size > 0) {
916 /* XXX: more correct headers */
917 h = 0;
918 if (st->codec->sub_id == 2)
919 h |= 1 << 26; /* mpeg 2 indicator */
920 q = s->buf;
921 *q++ = h >> 24;
922 *q++ = h >> 16;
923 *q++ = h >> 8;
924 *q++ = h;
925
926 if (st->codec->sub_id == 2) {
927 h = 0;
928 *q++ = h >> 24;
929 *q++ = h >> 16;
930 *q++ = h >> 8;
931 *q++ = h;
932 }
933
934 len = max_packet_size - (q - s->buf);
935 if (len > size)
936 len = size;
937
938 memcpy(q, buf1, len);
939 q += len;
940
941 /* 90 KHz time stamp */
942 s->timestamp = s->base_timestamp +
943 av_rescale((int64_t)s->cur_timestamp * st->codec->time_base.num, 90000, st->codec->time_base.den); //FIXME pass timestamps
944 rtp_send_data(s1, s->buf, q - s->buf, (len == size));
945
946 buf1 += len;
947 size -= len;
948 }
949 s->cur_timestamp++;
950 }
951
952 static void rtp_send_raw(AVFormatContext *s1,
953 const uint8_t *buf1, int size)
954 {
955 RTPDemuxContext *s = s1->priv_data;
956 AVStream *st = s1->streams[0];
957 int len, max_packet_size;
958
959 max_packet_size = s->max_payload_size;
960
961 while (size > 0) {
962 len = max_packet_size;
963 if (len > size)
964 len = size;
965
966 /* 90 KHz time stamp */
967 s->timestamp = s->base_timestamp +
968 av_rescale((int64_t)s->cur_timestamp * st->codec->time_base.num, 90000, st->codec->time_base.den); //FIXME pass timestamps
969 rtp_send_data(s1, buf1, len, (len == size));
970
971 buf1 += len;
972 size -= len;
973 }
974 s->cur_timestamp++;
975 }
976
977 /* NOTE: size is assumed to be an integer multiple of TS_PACKET_SIZE */
978 static void rtp_send_mpegts_raw(AVFormatContext *s1,
979 const uint8_t *buf1, int size)
980 {
981 RTPDemuxContext *s = s1->priv_data;
982 int len, out_len;
983
984 while (size >= TS_PACKET_SIZE) {
985 len = s->max_payload_size - (s->buf_ptr - s->buf);
986 if (len > size)
987 len = size;
988 memcpy(s->buf_ptr, buf1, len);
989 buf1 += len;
990 size -= len;
991 s->buf_ptr += len;
992
993 out_len = s->buf_ptr - s->buf;
994 if (out_len >= s->max_payload_size) {
995 rtp_send_data(s1, s->buf, out_len, 0);
996 s->buf_ptr = s->buf;
997 }
998 }
999 }
1000
1001 /* write an RTP packet. 'buf1' must contain a single specific frame. */
1002 static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
1003 {
1004 RTPDemuxContext *s = s1->priv_data;
1005 AVStream *st = s1->streams[0];
1006 int rtcp_bytes;
1007 int64_t ntp_time;
1008 int size= pkt->size;
1009 uint8_t *buf1= pkt->data;
1010
1011 #ifdef DEBUG
1012 printf("%d: write len=%d\n", pkt->stream_index, size);
1013 #endif
1014
1015 /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
1016 rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) /
1017 RTCP_TX_RATIO_DEN;
1018 if (s->first_packet || rtcp_bytes >= 28) {
1019 /* compute NTP time */
1020 /* XXX: 90 kHz timestamp hardcoded */
1021 ntp_time = (pkt->pts << 28) / 5625;
1022 rtcp_send_sr(s1, ntp_time);
1023 s->last_octet_count = s->octet_count;
1024 s->first_packet = 0;
1025 }
1026
1027 switch(st->codec->codec_id) {
1028 case CODEC_ID_PCM_MULAW:
1029 case CODEC_ID_PCM_ALAW:
1030 case CODEC_ID_PCM_U8:
1031 case CODEC_ID_PCM_S8:
1032 rtp_send_samples(s1, buf1, size, 1 * st->codec->channels);
1033 break;
1034 case CODEC_ID_PCM_U16BE:
1035 case CODEC_ID_PCM_U16LE:
1036 case CODEC_ID_PCM_S16BE:
1037 case CODEC_ID_PCM_S16LE:
1038 rtp_send_samples(s1, buf1, size, 2 * st->codec->channels);
1039 break;
1040 case CODEC_ID_MP2:
1041 case CODEC_ID_MP3:
1042 rtp_send_mpegaudio(s1, buf1, size);
1043 break;
1044 case CODEC_ID_MPEG1VIDEO:
1045 rtp_send_mpegvideo(s1, buf1, size);
1046 break;
1047 case CODEC_ID_MPEG2TS:
1048 rtp_send_mpegts_raw(s1, buf1, size);
1049 break;
1050 default:
1051 /* better than nothing : send the codec raw data */
1052 rtp_send_raw(s1, buf1, size);
1053 break;
1054 }
1055 return 0;
1056 }
1057
1058 AVOutputFormat rtp_muxer = {
1059 "rtp",
1060 "RTP output format",
1061 NULL,
1062 NULL,
1063 sizeof(RTPDemuxContext),
1064 CODEC_ID_PCM_MULAW,
1065 CODEC_ID_NONE,
1066 rtp_write_header,
1067 rtp_write_packet,
1068 };