Mercurial > libavformat.hg
comparison rtp.c @ 294:6091b76cfc2a libavformat
added MPEG2TS support in RTP, SDP and RTSP - replaced fake RTP demux by a specific API
author | bellard |
---|---|
date | Wed, 29 Oct 2003 14:25:27 +0000 |
parents | 3d92f793fd67 |
children | ef53bff8bf23 |
comparison
equal
deleted
inserted
replaced
293:62cec412a186 | 294:6091b76cfc2a |
---|---|
15 * You should have received a copy of the GNU Lesser General Public | 15 * You should have received a copy of the GNU Lesser General Public |
16 * License along with this library; if not, write to the Free Software | 16 * License along with this library; if not, write to the Free Software |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 */ | 18 */ |
19 #include "avformat.h" | 19 #include "avformat.h" |
20 #include "mpegts.h" | |
20 | 21 |
21 #include <unistd.h> | 22 #include <unistd.h> |
22 #include <sys/types.h> | 23 #include <sys/types.h> |
23 #include <sys/socket.h> | 24 #include <sys/socket.h> |
24 #include <netinet/in.h> | 25 #include <netinet/in.h> |
70 RTCP_SDES_IMG = 9, | 71 RTCP_SDES_IMG = 9, |
71 RTCP_SDES_DOOR = 10, | 72 RTCP_SDES_DOOR = 10, |
72 RTCP_SDES_SOURCE = 11 | 73 RTCP_SDES_SOURCE = 11 |
73 } rtcp_sdes_type_t; | 74 } rtcp_sdes_type_t; |
74 | 75 |
75 enum RTPPayloadType { | 76 struct RTPDemuxContext { |
76 RTP_PT_ULAW = 0, | 77 AVFormatContext *ic; |
77 RTP_PT_GSM = 3, | 78 AVStream *st; |
78 RTP_PT_G723 = 4, | |
79 RTP_PT_ALAW = 8, | |
80 RTP_PT_S16BE_STEREO = 10, | |
81 RTP_PT_S16BE_MONO = 11, | |
82 RTP_PT_MPEGAUDIO = 14, | |
83 RTP_PT_JPEG = 26, | |
84 RTP_PT_H261 = 31, | |
85 RTP_PT_MPEGVIDEO = 32, | |
86 RTP_PT_MPEG2TS = 33, | |
87 RTP_PT_H263 = 34, /* old H263 encapsulation */ | |
88 RTP_PT_PRIVATE = 96, | |
89 }; | |
90 | |
91 typedef struct RTPContext { | |
92 int payload_type; | 79 int payload_type; |
93 uint32_t ssrc; | 80 uint32_t ssrc; |
94 uint16_t seq; | 81 uint16_t seq; |
95 uint32_t timestamp; | 82 uint32_t timestamp; |
96 uint32_t base_timestamp; | 83 uint32_t base_timestamp; |
97 uint32_t cur_timestamp; | 84 uint32_t cur_timestamp; |
98 int max_payload_size; | 85 int max_payload_size; |
86 MpegTSContext *ts; /* only used for RTP_PT_MPEG2TS payloads */ | |
87 int read_buf_index; | |
88 int read_buf_size; | |
89 | |
99 /* rtcp sender statistics receive */ | 90 /* rtcp sender statistics receive */ |
100 int64_t last_rtcp_ntp_time; | 91 int64_t last_rtcp_ntp_time; |
101 int64_t first_rtcp_ntp_time; | 92 int64_t first_rtcp_ntp_time; |
102 uint32_t last_rtcp_timestamp; | 93 uint32_t last_rtcp_timestamp; |
103 /* rtcp sender statistics */ | 94 /* rtcp sender statistics */ |
106 unsigned int last_octet_count; | 97 unsigned int last_octet_count; |
107 int first_packet; | 98 int first_packet; |
108 /* buffer for output */ | 99 /* buffer for output */ |
109 uint8_t buf[RTP_MAX_PACKET_LENGTH]; | 100 uint8_t buf[RTP_MAX_PACKET_LENGTH]; |
110 uint8_t *buf_ptr; | 101 uint8_t *buf_ptr; |
111 } RTPContext; | 102 }; |
112 | 103 |
113 int rtp_get_codec_info(AVCodecContext *codec, int payload_type) | 104 int rtp_get_codec_info(AVCodecContext *codec, int payload_type) |
114 { | 105 { |
115 switch(payload_type) { | 106 switch(payload_type) { |
116 case RTP_PT_ULAW: | 107 case RTP_PT_ULAW: |
108 codec->codec_type = CODEC_TYPE_AUDIO; | |
117 codec->codec_id = CODEC_ID_PCM_MULAW; | 109 codec->codec_id = CODEC_ID_PCM_MULAW; |
118 codec->channels = 1; | 110 codec->channels = 1; |
119 codec->sample_rate = 8000; | 111 codec->sample_rate = 8000; |
120 break; | 112 break; |
121 case RTP_PT_ALAW: | 113 case RTP_PT_ALAW: |
114 codec->codec_type = CODEC_TYPE_AUDIO; | |
122 codec->codec_id = CODEC_ID_PCM_ALAW; | 115 codec->codec_id = CODEC_ID_PCM_ALAW; |
123 codec->channels = 1; | 116 codec->channels = 1; |
124 codec->sample_rate = 8000; | 117 codec->sample_rate = 8000; |
125 break; | 118 break; |
126 case RTP_PT_S16BE_STEREO: | 119 case RTP_PT_S16BE_STEREO: |
120 codec->codec_type = CODEC_TYPE_AUDIO; | |
127 codec->codec_id = CODEC_ID_PCM_S16BE; | 121 codec->codec_id = CODEC_ID_PCM_S16BE; |
128 codec->channels = 2; | 122 codec->channels = 2; |
129 codec->sample_rate = 44100; | 123 codec->sample_rate = 44100; |
130 break; | 124 break; |
131 case RTP_PT_S16BE_MONO: | 125 case RTP_PT_S16BE_MONO: |
126 codec->codec_type = CODEC_TYPE_AUDIO; | |
132 codec->codec_id = CODEC_ID_PCM_S16BE; | 127 codec->codec_id = CODEC_ID_PCM_S16BE; |
133 codec->channels = 1; | 128 codec->channels = 1; |
134 codec->sample_rate = 44100; | 129 codec->sample_rate = 44100; |
135 break; | 130 break; |
136 case RTP_PT_MPEGAUDIO: | 131 case RTP_PT_MPEGAUDIO: |
132 codec->codec_type = CODEC_TYPE_AUDIO; | |
137 codec->codec_id = CODEC_ID_MP2; | 133 codec->codec_id = CODEC_ID_MP2; |
138 break; | 134 break; |
139 case RTP_PT_JPEG: | 135 case RTP_PT_JPEG: |
136 codec->codec_type = CODEC_TYPE_VIDEO; | |
140 codec->codec_id = CODEC_ID_MJPEG; | 137 codec->codec_id = CODEC_ID_MJPEG; |
141 break; | 138 break; |
142 case RTP_PT_MPEGVIDEO: | 139 case RTP_PT_MPEGVIDEO: |
140 codec->codec_type = CODEC_TYPE_VIDEO; | |
143 codec->codec_id = CODEC_ID_MPEG1VIDEO; | 141 codec->codec_id = CODEC_ID_MPEG1VIDEO; |
142 break; | |
143 case RTP_PT_MPEG2TS: | |
144 codec->codec_type = CODEC_TYPE_DATA; | |
145 codec->codec_id = CODEC_ID_MPEG2TS; | |
144 break; | 146 break; |
145 default: | 147 default: |
146 return -1; | 148 return -1; |
147 } | 149 } |
148 return 0; | 150 return 0; |
177 payload_type = RTP_PT_JPEG; | 179 payload_type = RTP_PT_JPEG; |
178 break; | 180 break; |
179 case CODEC_ID_MPEG1VIDEO: | 181 case CODEC_ID_MPEG1VIDEO: |
180 payload_type = RTP_PT_MPEGVIDEO; | 182 payload_type = RTP_PT_MPEGVIDEO; |
181 break; | 183 break; |
184 case CODEC_ID_MPEG2TS: | |
185 payload_type = RTP_PT_MPEG2TS; | |
186 break; | |
182 default: | 187 default: |
183 break; | 188 break; |
184 } | 189 } |
185 return payload_type; | 190 return payload_type; |
186 } | 191 } |
193 static inline uint64_t decode_be64(const uint8_t *p) | 198 static inline uint64_t decode_be64(const uint8_t *p) |
194 { | 199 { |
195 return ((uint64_t)decode_be32(p) << 32) | decode_be32(p + 4); | 200 return ((uint64_t)decode_be32(p) << 32) | decode_be32(p + 4); |
196 } | 201 } |
197 | 202 |
198 static int rtcp_parse_packet(AVFormatContext *s1, const unsigned char *buf, int len) | 203 static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int len) |
199 { | 204 { |
200 RTPContext *s = s1->priv_data; | |
201 | |
202 if (buf[1] != 200) | 205 if (buf[1] != 200) |
203 return -1; | 206 return -1; |
204 s->last_rtcp_ntp_time = decode_be64(buf + 8); | 207 s->last_rtcp_ntp_time = decode_be64(buf + 8); |
205 if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) | 208 if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) |
206 s->first_rtcp_ntp_time = s->last_rtcp_ntp_time; | 209 s->first_rtcp_ntp_time = s->last_rtcp_ntp_time; |
207 s->last_rtcp_timestamp = decode_be32(buf + 16); | 210 s->last_rtcp_timestamp = decode_be32(buf + 16); |
208 return 0; | 211 return 0; |
209 } | 212 } |
210 | 213 |
211 /** | 214 /** |
212 * Parse an RTP packet directly sent as raw data. Can only be used if | 215 * open a new RTP parse context for stream 'st'. 'st' can be NULL for |
213 * 'raw' is given as input file | 216 * MPEG2TS streams to indicate that they should be demuxed inside the |
214 * @param s1 media file context | 217 * rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned) |
218 */ | |
219 RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, int payload_type) | |
220 { | |
221 RTPDemuxContext *s; | |
222 | |
223 s = av_mallocz(sizeof(RTPDemuxContext)); | |
224 if (!s) | |
225 return NULL; | |
226 s->payload_type = payload_type; | |
227 s->last_rtcp_ntp_time = AV_NOPTS_VALUE; | |
228 s->first_rtcp_ntp_time = AV_NOPTS_VALUE; | |
229 s->ic = s1; | |
230 s->st = st; | |
231 if (payload_type == RTP_PT_MPEG2TS) { | |
232 s->ts = mpegts_parse_open(s->ic); | |
233 if (s->ts == NULL) { | |
234 av_free(s); | |
235 return NULL; | |
236 } | |
237 } | |
238 return s; | |
239 } | |
240 | |
241 /** | |
242 * Parse an RTP or RTCP packet directly sent as a buffer. | |
243 * @param s RTP parse context. | |
215 * @param pkt returned packet | 244 * @param pkt returned packet |
216 * @param buf input buffer | 245 * @param buf input buffer or NULL to read the next packets |
217 * @param len buffer len | 246 * @param len buffer len |
218 * @return zero if no error. | 247 * @return 0 if a packet is returned, 1 if a packet is returned and more can follow |
248 * (use buf as NULL to read the next). -1 if no packet (error or no more packet). | |
219 */ | 249 */ |
220 int rtp_parse_packet(AVFormatContext *s1, AVPacket *pkt, | 250 int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt, |
221 const unsigned char *buf, int len) | 251 const uint8_t *buf, int len) |
222 { | 252 { |
223 RTPContext *s = s1->priv_data; | |
224 unsigned int ssrc, h; | 253 unsigned int ssrc, h; |
225 int payload_type, seq, delta_timestamp; | 254 int payload_type, seq, delta_timestamp, ret; |
226 AVStream *st; | 255 AVStream *st; |
227 uint32_t timestamp; | 256 uint32_t timestamp; |
228 | 257 |
258 if (!buf) { | |
259 /* return the next packets, if any */ | |
260 if (s->read_buf_index >= s->read_buf_size) | |
261 return -1; | |
262 ret = mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index, | |
263 s->read_buf_size - s->read_buf_index); | |
264 if (ret < 0) | |
265 return -1; | |
266 s->read_buf_index += ret; | |
267 if (s->read_buf_index < s->read_buf_size) | |
268 return 1; | |
269 else | |
270 return 0; | |
271 } | |
272 | |
229 if (len < 12) | 273 if (len < 12) |
230 return -1; | 274 return -1; |
231 | 275 |
232 if ((buf[0] & 0xc0) != (RTP_VERSION << 6)) | 276 if ((buf[0] & 0xc0) != (RTP_VERSION << 6)) |
233 return -1; | 277 return -1; |
234 if (buf[1] >= 200 && buf[1] <= 204) { | 278 if (buf[1] >= 200 && buf[1] <= 204) { |
235 rtcp_parse_packet(s1, buf, len); | 279 rtcp_parse_packet(s, buf, len); |
236 return -1; | 280 return -1; |
237 } | 281 } |
238 payload_type = buf[1] & 0x7f; | 282 payload_type = buf[1] & 0x7f; |
239 seq = (buf[2] << 8) | buf[3]; | 283 seq = (buf[2] << 8) | buf[3]; |
240 timestamp = decode_be32(buf + 4); | 284 timestamp = decode_be32(buf + 4); |
241 ssrc = decode_be32(buf + 8); | 285 ssrc = decode_be32(buf + 8); |
242 | 286 |
243 if (s->payload_type < 0) { | |
244 s->payload_type = payload_type; | |
245 | |
246 if (payload_type == RTP_PT_MPEG2TS) { | |
247 /* XXX: special case : not a single codec but a whole stream */ | |
248 return -1; | |
249 } else { | |
250 st = av_new_stream(s1, 0); | |
251 if (!st) | |
252 return -1; | |
253 rtp_get_codec_info(&st->codec, payload_type); | |
254 } | |
255 } | |
256 | |
257 /* NOTE: we can handle only one payload type */ | 287 /* NOTE: we can handle only one payload type */ |
258 if (s->payload_type != payload_type) | 288 if (s->payload_type != payload_type) |
259 return -1; | 289 return -1; |
260 #if defined(DEBUG) || 1 | 290 #if defined(DEBUG) || 1 |
261 if (seq != ((s->seq + 1) & 0xffff)) { | 291 if (seq != ((s->seq + 1) & 0xffff)) { |
264 } | 294 } |
265 s->seq = seq; | 295 s->seq = seq; |
266 #endif | 296 #endif |
267 len -= 12; | 297 len -= 12; |
268 buf += 12; | 298 buf += 12; |
269 st = s1->streams[0]; | 299 |
270 switch(st->codec.codec_id) { | 300 st = s->st; |
271 case CODEC_ID_MP2: | 301 if (!st) { |
272 /* better than nothing: skip mpeg audio RTP header */ | 302 /* specific MPEG2TS demux support */ |
273 if (len <= 4) | 303 ret = mpegts_parse_packet(s->ts, pkt, buf, len); |
304 if (ret < 0) | |
274 return -1; | 305 return -1; |
275 h = decode_be32(buf); | 306 if (ret < len) { |
276 len -= 4; | 307 s->read_buf_size = len - ret; |
277 buf += 4; | 308 memcpy(s->buf, buf + ret, s->read_buf_size); |
278 av_new_packet(pkt, len); | 309 s->read_buf_index = 0; |
279 memcpy(pkt->data, buf, len); | 310 return 1; |
280 break; | 311 } |
281 case CODEC_ID_MPEG1VIDEO: | 312 } else { |
282 /* better than nothing: skip mpeg audio RTP header */ | 313 switch(st->codec.codec_id) { |
283 if (len <= 4) | 314 case CODEC_ID_MP2: |
284 return -1; | 315 /* better than nothing: skip mpeg audio RTP header */ |
285 h = decode_be32(buf); | |
286 buf += 4; | |
287 len -= 4; | |
288 if (h & (1 << 26)) { | |
289 /* mpeg2 */ | |
290 if (len <= 4) | 316 if (len <= 4) |
291 return -1; | 317 return -1; |
318 h = decode_be32(buf); | |
319 len -= 4; | |
320 buf += 4; | |
321 av_new_packet(pkt, len); | |
322 memcpy(pkt->data, buf, len); | |
323 break; | |
324 case CODEC_ID_MPEG1VIDEO: | |
325 /* better than nothing: skip mpeg audio RTP header */ | |
326 if (len <= 4) | |
327 return -1; | |
328 h = decode_be32(buf); | |
292 buf += 4; | 329 buf += 4; |
293 len -= 4; | 330 len -= 4; |
294 } | 331 if (h & (1 << 26)) { |
295 av_new_packet(pkt, len); | 332 /* mpeg2 */ |
296 memcpy(pkt->data, buf, len); | 333 if (len <= 4) |
297 break; | 334 return -1; |
298 default: | 335 buf += 4; |
299 av_new_packet(pkt, len); | 336 len -= 4; |
300 memcpy(pkt->data, buf, len); | 337 } |
301 break; | 338 av_new_packet(pkt, len); |
302 } | 339 memcpy(pkt->data, buf, len); |
303 | 340 break; |
304 switch(st->codec.codec_id) { | 341 default: |
305 case CODEC_ID_MP2: | 342 av_new_packet(pkt, len); |
306 case CODEC_ID_MPEG1VIDEO: | 343 memcpy(pkt->data, buf, len); |
307 if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) { | 344 break; |
308 int64_t addend; | 345 } |
309 /* XXX: is it really necessary to unify the timestamp base ? */ | 346 |
310 /* compute pts from timestamp with received ntp_time */ | 347 switch(st->codec.codec_id) { |
311 delta_timestamp = timestamp - s->last_rtcp_timestamp; | 348 case CODEC_ID_MP2: |
312 /* convert to 90 kHz without overflow */ | 349 case CODEC_ID_MPEG1VIDEO: |
313 addend = (s->last_rtcp_ntp_time - s->first_rtcp_ntp_time) >> 14; | 350 if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) { |
314 addend = (addend * 5625) >> 14; | 351 int64_t addend; |
315 pkt->pts = addend + delta_timestamp; | 352 /* XXX: is it really necessary to unify the timestamp base ? */ |
316 } | 353 /* compute pts from timestamp with received ntp_time */ |
317 break; | 354 delta_timestamp = timestamp - s->last_rtcp_timestamp; |
318 default: | 355 /* convert to 90 kHz without overflow */ |
319 /* no timestamp info yet */ | 356 addend = (s->last_rtcp_ntp_time - s->first_rtcp_ntp_time) >> 14; |
320 break; | 357 addend = (addend * 5625) >> 14; |
358 pkt->pts = addend + delta_timestamp; | |
359 } | |
360 break; | |
361 default: | |
362 /* no timestamp info yet */ | |
363 break; | |
364 } | |
365 pkt->stream_index = s->st->index; | |
321 } | 366 } |
322 return 0; | 367 return 0; |
323 } | 368 } |
324 | 369 |
325 static int rtp_read_header(AVFormatContext *s1, | 370 void rtp_parse_close(RTPDemuxContext *s) |
326 AVFormatParameters *ap) | 371 { |
327 { | 372 if (s->payload_type == RTP_PT_MPEG2TS) { |
328 RTPContext *s = s1->priv_data; | 373 mpegts_parse_close(s->ts); |
329 s->payload_type = -1; | 374 } |
330 s->last_rtcp_ntp_time = AV_NOPTS_VALUE; | 375 av_free(s); |
331 s->first_rtcp_ntp_time = AV_NOPTS_VALUE; | |
332 return 0; | |
333 } | |
334 | |
335 static int rtp_read_packet(AVFormatContext *s1, AVPacket *pkt) | |
336 { | |
337 char buf[RTP_MAX_PACKET_LENGTH]; | |
338 int ret; | |
339 | |
340 /* XXX: needs a better API for packet handling ? */ | |
341 for(;;) { | |
342 ret = url_read(url_fileno(&s1->pb), buf, sizeof(buf)); | |
343 if (ret < 0) | |
344 return AVERROR_IO; | |
345 if (rtp_parse_packet(s1, pkt, buf, ret) == 0) | |
346 break; | |
347 } | |
348 return 0; | |
349 } | |
350 | |
351 static int rtp_read_close(AVFormatContext *s1) | |
352 { | |
353 // RTPContext *s = s1->priv_data; | |
354 return 0; | |
355 } | |
356 | |
357 static int rtp_probe(AVProbeData *p) | |
358 { | |
359 if (strstart(p->filename, "rtp://", NULL)) | |
360 return AVPROBE_SCORE_MAX; | |
361 return 0; | |
362 } | 376 } |
363 | 377 |
364 /* rtp output */ | 378 /* rtp output */ |
365 | 379 |
366 static int rtp_write_header(AVFormatContext *s1) | 380 static int rtp_write_header(AVFormatContext *s1) |
367 { | 381 { |
368 RTPContext *s = s1->priv_data; | 382 RTPDemuxContext *s = s1->priv_data; |
369 int payload_type, max_packet_size; | 383 int payload_type, max_packet_size, n; |
370 AVStream *st; | 384 AVStream *st; |
371 | 385 |
372 if (s1->nb_streams != 1) | 386 if (s1->nb_streams != 1) |
373 return -1; | 387 return -1; |
374 st = s1->streams[0]; | 388 st = s1->streams[0]; |
395 s->cur_timestamp = 0; | 409 s->cur_timestamp = 0; |
396 break; | 410 break; |
397 case CODEC_ID_MPEG1VIDEO: | 411 case CODEC_ID_MPEG1VIDEO: |
398 s->cur_timestamp = 0; | 412 s->cur_timestamp = 0; |
399 break; | 413 break; |
414 case CODEC_ID_MPEG2TS: | |
415 n = s->max_payload_size / TS_PACKET_SIZE; | |
416 if (n < 1) | |
417 n = 1; | |
418 s->max_payload_size = n * TS_PACKET_SIZE; | |
419 s->buf_ptr = s->buf; | |
420 break; | |
400 default: | 421 default: |
401 s->buf_ptr = s->buf; | 422 s->buf_ptr = s->buf; |
402 break; | 423 break; |
403 } | 424 } |
404 | 425 |
406 } | 427 } |
407 | 428 |
408 /* send an rtcp sender report packet */ | 429 /* send an rtcp sender report packet */ |
409 static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time) | 430 static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time) |
410 { | 431 { |
411 RTPContext *s = s1->priv_data; | 432 RTPDemuxContext *s = s1->priv_data; |
412 #if defined(DEBUG) | 433 #if defined(DEBUG) |
413 printf("RTCP: %02x %Lx %x\n", s->payload_type, ntp_time, s->timestamp); | 434 printf("RTCP: %02x %Lx %x\n", s->payload_type, ntp_time, s->timestamp); |
414 #endif | 435 #endif |
415 put_byte(&s1->pb, (RTP_VERSION << 6)); | 436 put_byte(&s1->pb, (RTP_VERSION << 6)); |
416 put_byte(&s1->pb, 200); | 437 put_byte(&s1->pb, 200); |
425 | 446 |
426 /* send an rtp packet. sequence number is incremented, but the caller | 447 /* send an rtp packet. sequence number is incremented, but the caller |
427 must update the timestamp itself */ | 448 must update the timestamp itself */ |
428 static void rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len) | 449 static void rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len) |
429 { | 450 { |
430 RTPContext *s = s1->priv_data; | 451 RTPDemuxContext *s = s1->priv_data; |
431 | 452 |
432 #ifdef DEBUG | 453 #ifdef DEBUG |
433 printf("rtp_send_data size=%d\n", len); | 454 printf("rtp_send_data size=%d\n", len); |
434 #endif | 455 #endif |
435 | 456 |
451 /* send an integer number of samples and compute time stamp and fill | 472 /* send an integer number of samples and compute time stamp and fill |
452 the rtp send buffer before sending. */ | 473 the rtp send buffer before sending. */ |
453 static void rtp_send_samples(AVFormatContext *s1, | 474 static void rtp_send_samples(AVFormatContext *s1, |
454 const uint8_t *buf1, int size, int sample_size) | 475 const uint8_t *buf1, int size, int sample_size) |
455 { | 476 { |
456 RTPContext *s = s1->priv_data; | 477 RTPDemuxContext *s = s1->priv_data; |
457 int len, max_packet_size, n; | 478 int len, max_packet_size, n; |
458 | 479 |
459 max_packet_size = (s->max_payload_size / sample_size) * sample_size; | 480 max_packet_size = (s->max_payload_size / sample_size) * sample_size; |
460 /* not needed, but who nows */ | 481 /* not needed, but who nows */ |
461 if ((size % sample_size) != 0) | 482 if ((size % sample_size) != 0) |
484 /* NOTE: we suppose that exactly one frame is given as argument here */ | 505 /* NOTE: we suppose that exactly one frame is given as argument here */ |
485 /* XXX: test it */ | 506 /* XXX: test it */ |
486 static void rtp_send_mpegaudio(AVFormatContext *s1, | 507 static void rtp_send_mpegaudio(AVFormatContext *s1, |
487 const uint8_t *buf1, int size) | 508 const uint8_t *buf1, int size) |
488 { | 509 { |
489 RTPContext *s = s1->priv_data; | 510 RTPDemuxContext *s = s1->priv_data; |
490 AVStream *st = s1->streams[0]; | 511 AVStream *st = s1->streams[0]; |
491 int len, count, max_packet_size; | 512 int len, count, max_packet_size; |
492 | 513 |
493 max_packet_size = s->max_payload_size; | 514 max_packet_size = s->max_payload_size; |
494 | 515 |
540 /* NOTE: a single frame must be passed with sequence header if | 561 /* NOTE: a single frame must be passed with sequence header if |
541 needed. XXX: use slices. */ | 562 needed. XXX: use slices. */ |
542 static void rtp_send_mpegvideo(AVFormatContext *s1, | 563 static void rtp_send_mpegvideo(AVFormatContext *s1, |
543 const uint8_t *buf1, int size) | 564 const uint8_t *buf1, int size) |
544 { | 565 { |
545 RTPContext *s = s1->priv_data; | 566 RTPDemuxContext *s = s1->priv_data; |
546 AVStream *st = s1->streams[0]; | 567 AVStream *st = s1->streams[0]; |
547 int len, h, max_packet_size; | 568 int len, h, max_packet_size; |
548 uint8_t *q; | 569 uint8_t *q; |
549 | 570 |
550 max_packet_size = s->max_payload_size; | 571 max_packet_size = s->max_payload_size; |
587 } | 608 } |
588 | 609 |
589 static void rtp_send_raw(AVFormatContext *s1, | 610 static void rtp_send_raw(AVFormatContext *s1, |
590 const uint8_t *buf1, int size) | 611 const uint8_t *buf1, int size) |
591 { | 612 { |
592 RTPContext *s = s1->priv_data; | 613 RTPDemuxContext *s = s1->priv_data; |
593 AVStream *st = s1->streams[0]; | 614 AVStream *st = s1->streams[0]; |
594 int len, max_packet_size; | 615 int len, max_packet_size; |
595 | 616 |
596 max_packet_size = s->max_payload_size; | 617 max_packet_size = s->max_payload_size; |
597 | 618 |
609 size -= len; | 630 size -= len; |
610 } | 631 } |
611 s->cur_timestamp++; | 632 s->cur_timestamp++; |
612 } | 633 } |
613 | 634 |
635 /* NOTE: size is assumed to be an integer multiple of TS_PACKET_SIZE */ | |
636 static void rtp_send_mpegts_raw(AVFormatContext *s1, | |
637 const uint8_t *buf1, int size) | |
638 { | |
639 RTPDemuxContext *s = s1->priv_data; | |
640 int len, out_len; | |
641 | |
642 while (size >= TS_PACKET_SIZE) { | |
643 len = s->max_payload_size - (s->buf_ptr - s->buf); | |
644 if (len > size) | |
645 len = size; | |
646 memcpy(s->buf_ptr, buf1, len); | |
647 buf1 += len; | |
648 size -= len; | |
649 s->buf_ptr += len; | |
650 | |
651 out_len = s->buf_ptr - s->buf; | |
652 if (out_len >= s->max_payload_size) { | |
653 rtp_send_data(s1, s->buf, out_len); | |
654 s->buf_ptr = s->buf; | |
655 } | |
656 } | |
657 } | |
658 | |
614 /* write an RTP packet. 'buf1' must contain a single specific frame. */ | 659 /* write an RTP packet. 'buf1' must contain a single specific frame. */ |
615 static int rtp_write_packet(AVFormatContext *s1, int stream_index, | 660 static int rtp_write_packet(AVFormatContext *s1, int stream_index, |
616 const uint8_t *buf1, int size, int64_t pts) | 661 const uint8_t *buf1, int size, int64_t pts) |
617 { | 662 { |
618 RTPContext *s = s1->priv_data; | 663 RTPDemuxContext *s = s1->priv_data; |
619 AVStream *st = s1->streams[0]; | 664 AVStream *st = s1->streams[0]; |
620 int rtcp_bytes; | 665 int rtcp_bytes; |
621 int64_t ntp_time; | 666 int64_t ntp_time; |
622 | 667 |
623 #ifdef DEBUG | 668 #ifdef DEBUG |
654 rtp_send_mpegaudio(s1, buf1, size); | 699 rtp_send_mpegaudio(s1, buf1, size); |
655 break; | 700 break; |
656 case CODEC_ID_MPEG1VIDEO: | 701 case CODEC_ID_MPEG1VIDEO: |
657 rtp_send_mpegvideo(s1, buf1, size); | 702 rtp_send_mpegvideo(s1, buf1, size); |
658 break; | 703 break; |
704 case CODEC_ID_MPEG2TS: | |
705 rtp_send_mpegts_raw(s1, buf1, size); | |
706 break; | |
659 default: | 707 default: |
660 /* better than nothing : send the codec raw data */ | 708 /* better than nothing : send the codec raw data */ |
661 rtp_send_raw(s1, buf1, size); | 709 rtp_send_raw(s1, buf1, size); |
662 break; | 710 break; |
663 } | 711 } |
664 return 0; | 712 return 0; |
665 } | 713 } |
666 | 714 |
667 static int rtp_write_trailer(AVFormatContext *s1) | 715 static int rtp_write_trailer(AVFormatContext *s1) |
668 { | 716 { |
669 // RTPContext *s = s1->priv_data; | 717 // RTPDemuxContext *s = s1->priv_data; |
670 return 0; | 718 return 0; |
671 } | 719 } |
672 | |
673 AVInputFormat rtp_demux = { | |
674 "rtp", | |
675 "RTP input format", | |
676 sizeof(RTPContext), | |
677 rtp_probe, | |
678 rtp_read_header, | |
679 rtp_read_packet, | |
680 rtp_read_close, | |
681 .flags = AVFMT_NOHEADER, | |
682 }; | |
683 | 720 |
684 AVOutputFormat rtp_mux = { | 721 AVOutputFormat rtp_mux = { |
685 "rtp", | 722 "rtp", |
686 "RTP output format", | 723 "RTP output format", |
687 NULL, | 724 NULL, |
688 NULL, | 725 NULL, |
689 sizeof(RTPContext), | 726 sizeof(RTPDemuxContext), |
690 CODEC_ID_PCM_MULAW, | 727 CODEC_ID_PCM_MULAW, |
691 CODEC_ID_NONE, | 728 CODEC_ID_NONE, |
692 rtp_write_header, | 729 rtp_write_header, |
693 rtp_write_packet, | 730 rtp_write_packet, |
694 rtp_write_trailer, | 731 rtp_write_trailer, |
695 }; | 732 }; |
696 | 733 |
697 int rtp_init(void) | 734 int rtp_init(void) |
698 { | 735 { |
699 av_register_output_format(&rtp_mux); | 736 av_register_output_format(&rtp_mux); |
700 av_register_input_format(&rtp_demux); | |
701 return 0; | 737 return 0; |
702 } | 738 } |