Mercurial > libavformat.hg
annotate rtp.c @ 173:38f64fabb24b libavformat
fixed NTP generation for mpeg
| author | bellard |
|---|---|
| date | Tue, 15 Jul 2003 19:41:40 +0000 |
| parents | 25062c9b1f86 |
| children | eb90c0a5a1ba |
| rev | line source |
|---|---|
| 0 | 1 /* |
| 2 * RTP input/output format | |
| 3 * Copyright (c) 2002 Fabrice Bellard. | |
| 4 * | |
| 5 * This library is free software; you can redistribute it and/or | |
| 6 * modify it under the terms of the GNU Lesser General Public | |
| 7 * License as published by the Free Software Foundation; either | |
| 8 * version 2 of the License, or (at your option) any later version. | |
| 9 * | |
| 10 * This library is distributed in the hope that it will be useful, | |
| 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 13 * Lesser General Public License for more details. | |
| 14 * | |
| 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 | |
| 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 18 */ | |
| 19 #include "avformat.h" | |
| 20 | |
| 21 #include <unistd.h> | |
| 22 #include <sys/types.h> | |
| 23 #include <sys/socket.h> | |
| 24 #include <netinet/in.h> | |
| 25 #ifndef __BEOS__ | |
| 26 # include <arpa/inet.h> | |
| 27 #else | |
| 28 # include "barpainet.h" | |
| 29 #endif | |
| 30 #include <netdb.h> | |
| 31 | |
| 32 //#define DEBUG | |
| 33 | |
| 34 | |
| 35 /* TODO: - add RTCP statistics reporting (should be optional). | |
| 36 | |
| 37 - add support for h263/mpeg4 packetized output : IDEA: send a | |
| 38 buffer to 'rtp_write_packet' contains all the packets for ONE | |
| 39 frame. Each packet should have a four byte header containing | |
| 40 the length in big endian format (same trick as | |
| 41 'url_open_dyn_packet_buf') | |
| 42 */ | |
| 43 | |
| 44 #define RTP_VERSION 2 | |
| 45 | |
| 46 #define RTP_MAX_SDES 256 /* maximum text length for SDES */ | |
| 47 | |
| 48 /* RTCP paquets use 0.5 % of the bandwidth */ | |
| 49 #define RTCP_TX_RATIO_NUM 5 | |
| 50 #define RTCP_TX_RATIO_DEN 1000 | |
| 51 | |
| 52 typedef enum { | |
| 53 RTCP_SR = 200, | |
| 54 RTCP_RR = 201, | |
| 55 RTCP_SDES = 202, | |
| 56 RTCP_BYE = 203, | |
| 57 RTCP_APP = 204 | |
| 58 } rtcp_type_t; | |
| 59 | |
| 60 typedef enum { | |
| 61 RTCP_SDES_END = 0, | |
| 62 RTCP_SDES_CNAME = 1, | |
| 63 RTCP_SDES_NAME = 2, | |
| 64 RTCP_SDES_EMAIL = 3, | |
| 65 RTCP_SDES_PHONE = 4, | |
| 66 RTCP_SDES_LOC = 5, | |
| 67 RTCP_SDES_TOOL = 6, | |
| 68 RTCP_SDES_NOTE = 7, | |
| 69 RTCP_SDES_PRIV = 8, | |
| 70 RTCP_SDES_IMG = 9, | |
| 71 RTCP_SDES_DOOR = 10, | |
| 72 RTCP_SDES_SOURCE = 11 | |
| 73 } rtcp_sdes_type_t; | |
| 74 | |
| 75 enum RTPPayloadType { | |
| 76 RTP_PT_ULAW = 0, | |
| 77 RTP_PT_GSM = 3, | |
| 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; | |
| 65 | 93 uint32_t ssrc; |
| 94 uint16_t seq; | |
| 95 uint32_t timestamp; | |
| 96 uint32_t base_timestamp; | |
| 97 uint32_t cur_timestamp; | |
| 0 | 98 int max_payload_size; |
| 99 /* rtcp sender statistics receive */ | |
| 65 | 100 int64_t last_rtcp_ntp_time; |
| 173 | 101 int64_t first_rtcp_ntp_time; |
| 65 | 102 uint32_t last_rtcp_timestamp; |
| 0 | 103 /* rtcp sender statistics */ |
| 104 unsigned int packet_count; | |
| 105 unsigned int octet_count; | |
| 106 unsigned int last_octet_count; | |
| 107 int first_packet; | |
| 108 /* buffer for output */ | |
| 65 | 109 uint8_t buf[RTP_MAX_PACKET_LENGTH]; |
| 110 uint8_t *buf_ptr; | |
| 0 | 111 } RTPContext; |
| 112 | |
| 113 int rtp_get_codec_info(AVCodecContext *codec, int payload_type) | |
| 114 { | |
| 115 switch(payload_type) { | |
| 116 case RTP_PT_ULAW: | |
| 117 codec->codec_id = CODEC_ID_PCM_MULAW; | |
| 118 codec->channels = 1; | |
| 119 codec->sample_rate = 8000; | |
| 120 break; | |
| 121 case RTP_PT_ALAW: | |
| 122 codec->codec_id = CODEC_ID_PCM_ALAW; | |
| 123 codec->channels = 1; | |
| 124 codec->sample_rate = 8000; | |
| 125 break; | |
| 126 case RTP_PT_S16BE_STEREO: | |
| 127 codec->codec_id = CODEC_ID_PCM_S16BE; | |
| 128 codec->channels = 2; | |
| 129 codec->sample_rate = 44100; | |
| 130 break; | |
| 131 case RTP_PT_S16BE_MONO: | |
| 132 codec->codec_id = CODEC_ID_PCM_S16BE; | |
| 133 codec->channels = 1; | |
| 134 codec->sample_rate = 44100; | |
| 135 break; | |
| 136 case RTP_PT_MPEGAUDIO: | |
| 137 codec->codec_id = CODEC_ID_MP2; | |
| 138 break; | |
| 139 case RTP_PT_JPEG: | |
| 140 codec->codec_id = CODEC_ID_MJPEG; | |
| 141 break; | |
| 142 case RTP_PT_MPEGVIDEO: | |
| 143 codec->codec_id = CODEC_ID_MPEG1VIDEO; | |
| 144 break; | |
| 145 default: | |
| 146 return -1; | |
| 147 } | |
| 148 return 0; | |
| 149 } | |
| 150 | |
| 151 /* return < 0 if unknown payload type */ | |
| 152 int rtp_get_payload_type(AVCodecContext *codec) | |
| 153 { | |
| 154 int payload_type; | |
| 155 | |
| 156 /* compute the payload type */ | |
| 157 payload_type = -1; | |
| 158 switch(codec->codec_id) { | |
| 159 case CODEC_ID_PCM_MULAW: | |
| 160 payload_type = RTP_PT_ULAW; | |
| 161 break; | |
| 162 case CODEC_ID_PCM_ALAW: | |
| 163 payload_type = RTP_PT_ALAW; | |
| 164 break; | |
| 165 case CODEC_ID_PCM_S16BE: | |
| 166 if (codec->channels == 1) { | |
| 167 payload_type = RTP_PT_S16BE_MONO; | |
| 168 } else if (codec->channels == 2) { | |
| 169 payload_type = RTP_PT_S16BE_STEREO; | |
| 170 } | |
| 171 break; | |
| 172 case CODEC_ID_MP2: | |
| 173 case CODEC_ID_MP3LAME: | |
| 174 payload_type = RTP_PT_MPEGAUDIO; | |
| 175 break; | |
| 176 case CODEC_ID_MJPEG: | |
| 177 payload_type = RTP_PT_JPEG; | |
| 178 break; | |
| 179 case CODEC_ID_MPEG1VIDEO: | |
| 180 payload_type = RTP_PT_MPEGVIDEO; | |
| 181 break; | |
| 182 default: | |
| 183 break; | |
| 184 } | |
| 185 return payload_type; | |
| 186 } | |
| 187 | |
| 65 | 188 static inline uint32_t decode_be32(const uint8_t *p) |
| 0 | 189 { |
| 190 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; | |
| 191 } | |
| 192 | |
| 173 | 193 static inline uint64_t decode_be64(const uint8_t *p) |
| 0 | 194 { |
| 65 | 195 return ((uint64_t)decode_be32(p) << 32) | decode_be32(p + 4); |
| 0 | 196 } |
| 197 | |
| 198 static int rtcp_parse_packet(AVFormatContext *s1, const unsigned char *buf, int len) | |
| 199 { | |
| 200 RTPContext *s = s1->priv_data; | |
| 201 | |
| 202 if (buf[1] != 200) | |
| 203 return -1; | |
| 204 s->last_rtcp_ntp_time = decode_be64(buf + 8); | |
| 173 | 205 if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) |
| 206 s->first_rtcp_ntp_time = s->last_rtcp_ntp_time; | |
| 0 | 207 s->last_rtcp_timestamp = decode_be32(buf + 16); |
| 208 return 0; | |
| 209 } | |
| 210 | |
| 211 /** | |
| 212 * Parse an RTP packet directly sent as raw data. Can only be used if | |
| 213 * 'raw' is given as input file | |
| 214 * @param s1 media file context | |
| 215 * @param pkt returned packet | |
| 216 * @param buf input buffer | |
| 217 * @param len buffer len | |
| 218 * @return zero if no error. | |
| 219 */ | |
| 220 int rtp_parse_packet(AVFormatContext *s1, AVPacket *pkt, | |
| 221 const unsigned char *buf, int len) | |
| 222 { | |
| 223 RTPContext *s = s1->priv_data; | |
| 224 unsigned int ssrc, h; | |
| 225 int payload_type, seq, delta_timestamp; | |
| 226 AVStream *st; | |
| 65 | 227 uint32_t timestamp; |
| 0 | 228 |
| 229 if (len < 12) | |
| 230 return -1; | |
| 231 | |
| 232 if ((buf[0] & 0xc0) != (RTP_VERSION << 6)) | |
| 233 return -1; | |
| 234 if (buf[1] >= 200 && buf[1] <= 204) { | |
| 235 rtcp_parse_packet(s1, buf, len); | |
| 236 return -1; | |
| 237 } | |
| 238 payload_type = buf[1] & 0x7f; | |
| 239 seq = (buf[2] << 8) | buf[3]; | |
| 240 timestamp = decode_be32(buf + 4); | |
| 241 ssrc = decode_be32(buf + 8); | |
| 242 | |
| 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 */ | |
| 258 if (s->payload_type != payload_type) | |
| 259 return -1; | |
| 260 #if defined(DEBUG) || 1 | |
| 261 if (seq != ((s->seq + 1) & 0xffff)) { | |
| 262 printf("RTP: PT=%02x: bad cseq %04x expected=%04x\n", | |
| 263 payload_type, seq, ((s->seq + 1) & 0xffff)); | |
| 264 } | |
| 265 s->seq = seq; | |
| 266 #endif | |
| 267 len -= 12; | |
| 268 buf += 12; | |
| 269 st = s1->streams[0]; | |
| 270 switch(st->codec.codec_id) { | |
| 271 case CODEC_ID_MP2: | |
| 272 /* better than nothing: skip mpeg audio RTP header */ | |
| 273 if (len <= 4) | |
| 274 return -1; | |
| 275 h = decode_be32(buf); | |
| 276 len -= 4; | |
| 277 buf += 4; | |
| 278 av_new_packet(pkt, len); | |
| 279 memcpy(pkt->data, buf, len); | |
| 280 break; | |
| 281 case CODEC_ID_MPEG1VIDEO: | |
| 282 /* better than nothing: skip mpeg audio RTP header */ | |
| 283 if (len <= 4) | |
| 284 return -1; | |
| 285 h = decode_be32(buf); | |
| 286 buf += 4; | |
| 287 len -= 4; | |
| 288 if (h & (1 << 26)) { | |
| 289 /* mpeg2 */ | |
| 290 if (len <= 4) | |
| 291 return -1; | |
| 292 buf += 4; | |
| 293 len -= 4; | |
| 294 } | |
| 295 av_new_packet(pkt, len); | |
| 296 memcpy(pkt->data, buf, len); | |
| 297 break; | |
| 298 default: | |
| 299 av_new_packet(pkt, len); | |
| 300 memcpy(pkt->data, buf, len); | |
| 301 break; | |
| 302 } | |
| 303 | |
| 173 | 304 switch(st->codec.codec_id) { |
| 305 case CODEC_ID_MP2: | |
| 306 case CODEC_ID_MPEG1VIDEO: | |
| 307 if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) { | |
| 308 int64_t addend; | |
| 309 /* XXX: is it really necessary to unify the timestamp base ? */ | |
| 310 /* compute pts from timestamp with received ntp_time */ | |
| 311 delta_timestamp = timestamp - s->last_rtcp_timestamp; | |
| 312 /* convert to 90 kHz without overflow */ | |
| 313 addend = (s->last_rtcp_ntp_time - s->first_rtcp_ntp_time) >> 14; | |
| 314 addend = (addend * 5625) >> 14; | |
| 315 pkt->pts = addend + delta_timestamp; | |
| 316 } | |
| 317 break; | |
| 318 default: | |
| 319 /* no timestamp info yet */ | |
| 320 break; | |
| 0 | 321 } |
| 322 return 0; | |
| 323 } | |
| 324 | |
| 325 static int rtp_read_header(AVFormatContext *s1, | |
| 326 AVFormatParameters *ap) | |
| 327 { | |
| 328 RTPContext *s = s1->priv_data; | |
| 329 s->payload_type = -1; | |
| 330 s->last_rtcp_ntp_time = AV_NOPTS_VALUE; | |
| 173 | 331 s->first_rtcp_ntp_time = AV_NOPTS_VALUE; |
| 0 | 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 } | |
| 363 | |
| 364 /* rtp output */ | |
| 365 | |
| 366 static int rtp_write_header(AVFormatContext *s1) | |
| 367 { | |
| 368 RTPContext *s = s1->priv_data; | |
| 369 int payload_type, max_packet_size; | |
| 370 AVStream *st; | |
| 371 | |
| 372 if (s1->nb_streams != 1) | |
| 373 return -1; | |
| 374 st = s1->streams[0]; | |
| 375 | |
| 376 payload_type = rtp_get_payload_type(&st->codec); | |
| 377 if (payload_type < 0) | |
| 378 payload_type = RTP_PT_PRIVATE; /* private payload type */ | |
| 379 s->payload_type = payload_type; | |
| 380 | |
| 381 s->base_timestamp = random(); | |
| 382 s->timestamp = s->base_timestamp; | |
| 383 s->ssrc = random(); | |
| 384 s->first_packet = 1; | |
| 385 | |
| 386 max_packet_size = url_fget_max_packet_size(&s1->pb); | |
| 387 if (max_packet_size <= 12) | |
| 388 return AVERROR_IO; | |
| 389 s->max_payload_size = max_packet_size - 12; | |
| 390 | |
| 391 switch(st->codec.codec_id) { | |
| 392 case CODEC_ID_MP2: | |
| 393 case CODEC_ID_MP3LAME: | |
| 394 s->buf_ptr = s->buf + 4; | |
| 395 s->cur_timestamp = 0; | |
| 396 break; | |
| 397 case CODEC_ID_MPEG1VIDEO: | |
| 398 s->cur_timestamp = 0; | |
| 399 break; | |
| 400 default: | |
| 401 s->buf_ptr = s->buf; | |
| 402 break; | |
| 403 } | |
| 404 | |
| 405 return 0; | |
| 406 } | |
| 407 | |
| 408 /* send an rtcp sender report packet */ | |
| 65 | 409 static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time) |
| 0 | 410 { |
| 411 RTPContext *s = s1->priv_data; | |
| 412 #if defined(DEBUG) | |
| 413 printf("RTCP: %02x %Lx %x\n", s->payload_type, ntp_time, s->timestamp); | |
| 414 #endif | |
| 415 put_byte(&s1->pb, (RTP_VERSION << 6)); | |
| 416 put_byte(&s1->pb, 200); | |
| 417 put_be16(&s1->pb, 6); /* length in words - 1 */ | |
| 418 put_be32(&s1->pb, s->ssrc); | |
| 419 put_be64(&s1->pb, ntp_time); | |
| 420 put_be32(&s1->pb, s->timestamp); | |
| 421 put_be32(&s1->pb, s->packet_count); | |
| 422 put_be32(&s1->pb, s->octet_count); | |
| 423 put_flush_packet(&s1->pb); | |
| 424 } | |
| 425 | |
| 426 /* send an rtp packet. sequence number is incremented, but the caller | |
| 427 must update the timestamp itself */ | |
| 65 | 428 static void rtp_send_data(AVFormatContext *s1, uint8_t *buf1, int len) |
| 0 | 429 { |
| 430 RTPContext *s = s1->priv_data; | |
| 431 | |
| 432 #ifdef DEBUG | |
| 433 printf("rtp_send_data size=%d\n", len); | |
| 434 #endif | |
| 435 | |
| 436 /* build the RTP header */ | |
| 437 put_byte(&s1->pb, (RTP_VERSION << 6)); | |
| 438 put_byte(&s1->pb, s->payload_type & 0x7f); | |
| 439 put_be16(&s1->pb, s->seq); | |
| 440 put_be32(&s1->pb, s->timestamp); | |
| 441 put_be32(&s1->pb, s->ssrc); | |
| 442 | |
| 443 put_buffer(&s1->pb, buf1, len); | |
| 444 put_flush_packet(&s1->pb); | |
| 445 | |
| 446 s->seq++; | |
| 447 s->octet_count += len; | |
| 448 s->packet_count++; | |
| 449 } | |
| 450 | |
| 451 /* send an integer number of samples and compute time stamp and fill | |
| 452 the rtp send buffer before sending. */ | |
| 453 static void rtp_send_samples(AVFormatContext *s1, | |
| 65 | 454 uint8_t *buf1, int size, int sample_size) |
| 0 | 455 { |
| 456 RTPContext *s = s1->priv_data; | |
| 457 int len, max_packet_size, n; | |
| 458 | |
| 459 max_packet_size = (s->max_payload_size / sample_size) * sample_size; | |
| 460 /* not needed, but who nows */ | |
| 461 if ((size % sample_size) != 0) | |
| 462 av_abort(); | |
| 463 while (size > 0) { | |
| 464 len = (max_packet_size - (s->buf_ptr - s->buf)); | |
| 465 if (len > size) | |
| 466 len = size; | |
| 467 | |
| 468 /* copy data */ | |
| 469 memcpy(s->buf_ptr, buf1, len); | |
| 470 s->buf_ptr += len; | |
| 471 buf1 += len; | |
| 472 size -= len; | |
| 473 n = (s->buf_ptr - s->buf); | |
| 474 /* if buffer full, then send it */ | |
| 475 if (n >= max_packet_size) { | |
| 476 rtp_send_data(s1, s->buf, n); | |
| 477 s->buf_ptr = s->buf; | |
| 478 /* update timestamp */ | |
| 479 s->timestamp += n / sample_size; | |
| 480 } | |
| 481 } | |
| 482 } | |
| 483 | |
| 484 /* NOTE: we suppose that exactly one frame is given as argument here */ | |
| 485 /* XXX: test it */ | |
| 486 static void rtp_send_mpegaudio(AVFormatContext *s1, | |
| 65 | 487 uint8_t *buf1, int size) |
| 0 | 488 { |
| 489 RTPContext *s = s1->priv_data; | |
| 490 AVStream *st = s1->streams[0]; | |
| 491 int len, count, max_packet_size; | |
| 492 | |
| 493 max_packet_size = s->max_payload_size; | |
| 494 | |
| 495 /* test if we must flush because not enough space */ | |
| 496 len = (s->buf_ptr - s->buf); | |
| 497 if ((len + size) > max_packet_size) { | |
| 498 if (len > 4) { | |
| 499 rtp_send_data(s1, s->buf, s->buf_ptr - s->buf); | |
| 500 s->buf_ptr = s->buf + 4; | |
| 501 /* 90 KHz time stamp */ | |
| 502 s->timestamp = s->base_timestamp + | |
| 503 (s->cur_timestamp * 90000LL) / st->codec.sample_rate; | |
| 504 } | |
| 505 } | |
| 506 | |
| 507 /* add the packet */ | |
| 508 if (size > max_packet_size) { | |
| 509 /* big packet: fragment */ | |
| 510 count = 0; | |
| 511 while (size > 0) { | |
| 512 len = max_packet_size - 4; | |
| 513 if (len > size) | |
| 514 len = size; | |
| 515 /* build fragmented packet */ | |
| 516 s->buf[0] = 0; | |
| 517 s->buf[1] = 0; | |
| 518 s->buf[2] = count >> 8; | |
| 519 s->buf[3] = count; | |
| 520 memcpy(s->buf + 4, buf1, len); | |
| 521 rtp_send_data(s1, s->buf, len + 4); | |
| 522 size -= len; | |
| 523 buf1 += len; | |
| 524 count += len; | |
| 525 } | |
| 526 } else { | |
| 527 if (s->buf_ptr == s->buf + 4) { | |
| 528 /* no fragmentation possible */ | |
| 529 s->buf[0] = 0; | |
| 530 s->buf[1] = 0; | |
| 531 s->buf[2] = 0; | |
| 532 s->buf[3] = 0; | |
| 533 } | |
| 534 memcpy(s->buf_ptr, buf1, size); | |
| 535 s->buf_ptr += size; | |
| 536 } | |
| 537 s->cur_timestamp += st->codec.frame_size; | |
| 538 } | |
| 539 | |
| 540 /* NOTE: a single frame must be passed with sequence header if | |
| 541 needed. XXX: use slices. */ | |
| 542 static void rtp_send_mpegvideo(AVFormatContext *s1, | |
| 65 | 543 uint8_t *buf1, int size) |
| 0 | 544 { |
| 545 RTPContext *s = s1->priv_data; | |
| 546 AVStream *st = s1->streams[0]; | |
| 547 int len, h, max_packet_size; | |
| 65 | 548 uint8_t *q; |
| 0 | 549 |
| 550 max_packet_size = s->max_payload_size; | |
| 551 | |
| 552 while (size > 0) { | |
| 553 /* XXX: more correct headers */ | |
| 554 h = 0; | |
| 555 if (st->codec.sub_id == 2) | |
| 556 h |= 1 << 26; /* mpeg 2 indicator */ | |
| 557 q = s->buf; | |
| 558 *q++ = h >> 24; | |
| 559 *q++ = h >> 16; | |
| 560 *q++ = h >> 8; | |
| 561 *q++ = h; | |
| 562 | |
| 563 if (st->codec.sub_id == 2) { | |
| 564 h = 0; | |
| 565 *q++ = h >> 24; | |
| 566 *q++ = h >> 16; | |
| 567 *q++ = h >> 8; | |
| 568 *q++ = h; | |
| 569 } | |
| 570 | |
| 571 len = max_packet_size - (q - s->buf); | |
| 572 if (len > size) | |
| 573 len = size; | |
| 574 | |
| 575 memcpy(q, buf1, len); | |
| 576 q += len; | |
| 577 | |
| 578 /* 90 KHz time stamp */ | |
| 579 s->timestamp = s->base_timestamp + | |
|
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
65
diff
changeset
|
580 av_rescale((int64_t)s->cur_timestamp * st->codec.frame_rate_base, 90000, st->codec.frame_rate); |
| 0 | 581 rtp_send_data(s1, s->buf, q - s->buf); |
| 582 | |
| 583 buf1 += len; | |
| 584 size -= len; | |
| 585 } | |
| 586 s->cur_timestamp++; | |
| 587 } | |
| 588 | |
| 589 static void rtp_send_raw(AVFormatContext *s1, | |
| 65 | 590 uint8_t *buf1, int size) |
| 0 | 591 { |
| 592 RTPContext *s = s1->priv_data; | |
| 593 AVStream *st = s1->streams[0]; | |
| 594 int len, max_packet_size; | |
| 595 | |
| 596 max_packet_size = s->max_payload_size; | |
| 597 | |
| 598 while (size > 0) { | |
| 599 len = max_packet_size; | |
| 600 if (len > size) | |
| 601 len = size; | |
| 602 | |
| 603 /* 90 KHz time stamp */ | |
| 604 s->timestamp = s->base_timestamp + | |
|
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
65
diff
changeset
|
605 av_rescale((int64_t)s->cur_timestamp * st->codec.frame_rate_base, 90000, st->codec.frame_rate); |
| 0 | 606 rtp_send_data(s1, buf1, len); |
| 607 | |
| 608 buf1 += len; | |
| 609 size -= len; | |
| 610 } | |
| 611 s->cur_timestamp++; | |
| 612 } | |
| 613 | |
| 614 /* write an RTP packet. 'buf1' must contain a single specific frame. */ | |
| 615 static int rtp_write_packet(AVFormatContext *s1, int stream_index, | |
| 65 | 616 uint8_t *buf1, int size, int force_pts) |
| 0 | 617 { |
| 618 RTPContext *s = s1->priv_data; | |
| 619 AVStream *st = s1->streams[0]; | |
| 620 int rtcp_bytes; | |
| 65 | 621 int64_t ntp_time; |
| 0 | 622 |
| 623 #ifdef DEBUG | |
| 624 printf("%d: write len=%d\n", stream_index, size); | |
| 625 #endif | |
| 626 | |
| 627 /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */ | |
| 628 rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) / | |
| 629 RTCP_TX_RATIO_DEN; | |
| 630 if (s->first_packet || rtcp_bytes >= 28) { | |
| 631 /* compute NTP time */ | |
| 173 | 632 /* XXX: 90 kHz timestamp hardcoded */ |
| 633 ntp_time = ((int64_t)force_pts << 28) / 5625; | |
| 0 | 634 rtcp_send_sr(s1, ntp_time); |
| 635 s->last_octet_count = s->octet_count; | |
| 636 s->first_packet = 0; | |
| 637 } | |
| 638 | |
| 639 switch(st->codec.codec_id) { | |
| 640 case CODEC_ID_PCM_MULAW: | |
| 641 case CODEC_ID_PCM_ALAW: | |
| 642 case CODEC_ID_PCM_U8: | |
| 643 case CODEC_ID_PCM_S8: | |
| 644 rtp_send_samples(s1, buf1, size, 1 * st->codec.channels); | |
| 645 break; | |
| 646 case CODEC_ID_PCM_U16BE: | |
| 647 case CODEC_ID_PCM_U16LE: | |
| 648 case CODEC_ID_PCM_S16BE: | |
| 649 case CODEC_ID_PCM_S16LE: | |
| 650 rtp_send_samples(s1, buf1, size, 2 * st->codec.channels); | |
| 651 break; | |
| 652 case CODEC_ID_MP2: | |
| 653 case CODEC_ID_MP3LAME: | |
| 654 rtp_send_mpegaudio(s1, buf1, size); | |
| 655 break; | |
| 656 case CODEC_ID_MPEG1VIDEO: | |
| 657 rtp_send_mpegvideo(s1, buf1, size); | |
| 658 break; | |
| 659 default: | |
| 660 /* better than nothing : send the codec raw data */ | |
| 661 rtp_send_raw(s1, buf1, size); | |
| 662 break; | |
| 663 } | |
| 664 return 0; | |
| 665 } | |
| 666 | |
| 667 static int rtp_write_trailer(AVFormatContext *s1) | |
| 668 { | |
| 669 // RTPContext *s = s1->priv_data; | |
| 670 return 0; | |
| 671 } | |
| 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 | |
| 684 AVOutputFormat rtp_mux = { | |
| 685 "rtp", | |
| 686 "RTP output format", | |
| 687 NULL, | |
| 688 NULL, | |
| 689 sizeof(RTPContext), | |
| 690 CODEC_ID_PCM_MULAW, | |
| 691 CODEC_ID_NONE, | |
| 692 rtp_write_header, | |
| 693 rtp_write_packet, | |
| 694 rtp_write_trailer, | |
| 695 }; | |
| 696 | |
| 697 int rtp_init(void) | |
| 698 { | |
| 699 av_register_output_format(&rtp_mux); | |
| 700 av_register_input_format(&rtp_demux); | |
| 701 return 0; | |
| 702 } |
