History

Merge commit '86d9181cf41edc3382bf2481f95a2fb321058689'

* commit '86d9181cf41edc3382bf2481f95a2fb321058689': rtpdec: Support sending RTCP feedback packets Conflicts: libavformat/version.h

Michael Niedermayer committed 13 years ago

Commit 34c1c082 parents 8c3ae9e 86d91815 files · +113 −1Browse files

Unified · Split

5 files
  1. libavformat/rtpdec.c +96 −0
  2. libavformat/rtpdec.h +5 −0
  3. libavformat/rtsp.c +8 −0
  4. libavformat/rtsp.h +3 −0
  5. libavformat/version.h +1 −1
libavformat/rtpdec.c+96−0
@@ -30,6 +30,8 @@ · 29 unmodified lines
30#include "rtpdec.h"30#include "rtpdec.h"
31#include "rtpdec_formats.h"31#include "rtpdec_formats.h"
32 32
33#define MIN_FEEDBACK_INTERVAL 200000 /* 200 ms in us */
34
33static RTPDynamicProtocolHandler realmedia_mp3_dynamic_handler = {35static RTPDynamicProtocolHandler realmedia_mp3_dynamic_handler = {
34 .enc_name = "X-MP3-draft-00",36 .enc_name = "X-MP3-draft-00",
35 .codec_type = AVMEDIA_TYPE_AUDIO,37 .codec_type = AVMEDIA_TYPE_AUDIO,
@@ -366,6 +368,100 @@ void ff_rtp_send_punch_packets(URLContext *rtp_handle) · 330 unmodified lines
366 av_free(buf);368 av_free(buf);
367}369}
368 370
371static int find_missing_packets(RTPDemuxContext *s, uint16_t *first_missing,
372 uint16_t *missing_mask)
373{
374 int i;
375 uint16_t next_seq = s->seq + 1;
376 RTPPacket *pkt = s->queue;
377
378 if (!pkt || pkt->seq == next_seq)
379 return 0;
380
381 *missing_mask = 0;
382 for (i = 1; i <= 16; i++) {
383 uint16_t missing_seq = next_seq + i;
384 while (pkt) {
385 int16_t diff = pkt->seq - missing_seq;
386 if (diff >= 0)
387 break;
388 pkt = pkt->next;
389 }
390 if (!pkt)
391 break;
392 if (pkt->seq == missing_seq)
393 continue;
394 *missing_mask |= 1 << (i - 1);
395 }
396
397 *first_missing = next_seq;
398 return 1;
399}
400
401int ff_rtp_send_rtcp_feedback(RTPDemuxContext *s, URLContext *fd,
402 AVIOContext *avio)
403{
404 int len, need_keyframe, missing_packets;
405 AVIOContext *pb;
406 uint8_t *buf;
407 int64_t now;
408 uint16_t first_missing, missing_mask;
409
410 if (!fd && !avio)
411 return -1;
412
413 need_keyframe = s->handler && s->handler->need_keyframe &&
414 s->handler->need_keyframe(s->dynamic_protocol_context);
415 missing_packets = find_missing_packets(s, &first_missing, &missing_mask);
416
417 if (!need_keyframe && !missing_packets)
418 return 0;
419
420 /* Send new feedback if enough time has elapsed since the last
421 * feedback packet. */
422
423 now = av_gettime();
424 if (s->last_feedback_time &&
425 (now - s->last_feedback_time) < MIN_FEEDBACK_INTERVAL)
426 return 0;
427 s->last_feedback_time = now;
428
429 if (!fd)
430 pb = avio;
431 else if (avio_open_dyn_buf(&pb) < 0)
432 return -1;
433
434 if (need_keyframe) {
435 avio_w8(pb, (RTP_VERSION << 6) | 1); /* PLI */
436 avio_w8(pb, RTCP_PSFB);
437 avio_wb16(pb, 2); /* length in words - 1 */
438 // our own SSRC: we use the server's SSRC + 1 to avoid conflicts
439 avio_wb32(pb, s->ssrc + 1);
440 avio_wb32(pb, s->ssrc); // server SSRC
441 }
442
443 if (missing_packets) {
444 avio_w8(pb, (RTP_VERSION << 6) | 1); /* NACK */
445 avio_w8(pb, RTCP_RTPFB);
446 avio_wb16(pb, 3); /* length in words - 1 */
447 avio_wb32(pb, s->ssrc + 1);
448 avio_wb32(pb, s->ssrc); // server SSRC
449
450 avio_wb16(pb, first_missing);
451 avio_wb16(pb, missing_mask);
452 }
453
454 avio_flush(pb);
455 if (!fd)
456 return 0;
457 len = avio_close_dyn_buf(pb, &buf);
458 if (len > 0 && buf) {
459 ffurl_write(fd, buf, len);
460 av_free(buf);
461 }
462 return 0;
463}
464
369/**465/**
370 * open a new RTP parse context for stream 'st'. 'st' can be NULL for466 * open a new RTP parse context for stream 'st'. 'st' can be NULL for
371 * MPEG2-TS streams to indicate that they should be demuxed inside the467 * MPEG2-TS streams to indicate that they should be demuxed inside the
libavformat/rtpdec.h+5−0
@@ -73,6 +73,8 @@ void ff_rtp_send_punch_packets(URLContext* rtp_handle); · 72 unmodified lines
73 */73 */
74int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd,74int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd,
75 AVIOContext *avio, int count);75 AVIOContext *avio, int count);
76int ff_rtp_send_rtcp_feedback(RTPDemuxContext *s, URLContext *fd,
77 AVIOContext *avio);
76 78
77// these statistics are used for rtcp receiver reports...79// these statistics are used for rtcp receiver reports...
78typedef struct RTPStatistics {80typedef struct RTPStatistics {
@@ -130,6 +132,7 @@ struct RTPDynamicProtocolHandler { · 51 unmodified lines
130 void (*free)(PayloadContext *protocol_data);132 void (*free)(PayloadContext *protocol_data);
131 /** Parse handler for this dynamic packet */133 /** Parse handler for this dynamic packet */
132 DynamicPayloadPacketHandlerProc parse_packet;134 DynamicPayloadPacketHandlerProc parse_packet;
135 int (*need_keyframe)(PayloadContext *context);
133 136
134 struct RTPDynamicProtocolHandler *next;137 struct RTPDynamicProtocolHandler *next;
135};138};
@@ -180,6 +183,8 @@ struct RTPDemuxContext { · 44 unmodified lines
180 unsigned int packet_count;183 unsigned int packet_count;
181 unsigned int octet_count;184 unsigned int octet_count;
182 unsigned int last_octet_count;185 unsigned int last_octet_count;
186 int64_t last_feedback_time;
187
183 /* buffer for partially parsed packets */188 /* buffer for partially parsed packets */
184 uint8_t buf[RTP_MAX_PACKET_LENGTH];189 uint8_t buf[RTP_MAX_PACKET_LENGTH];
185 190
libavformat/rtsp.c+8−0
@@ -380,6 +380,8 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, · 379 unmodified lines
380 get_word(buf1, sizeof(buf1), &p); /* protocol */380 get_word(buf1, sizeof(buf1), &p); /* protocol */
381 if (!strcmp(buf1, "udp"))381 if (!strcmp(buf1, "udp"))
382 rt->transport = RTSP_TRANSPORT_RAW;382 rt->transport = RTSP_TRANSPORT_RAW;
383 else if (strstr(buf1, "/AVPF") || strstr(buf1, "/SAVPF"))
384 rtsp_st->feedback = 1;
383 385
384 /* XXX: handle list of formats */386 /* XXX: handle list of formats */
385 get_word(buf1, sizeof(buf1), &p); /* format list */387 get_word(buf1, sizeof(buf1), &p); /* format list */
@@ -1932,6 +1934,12 @@ redo: · 1546 unmodified lines
1932 ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);1934 ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
1933 } else if (rt->transport == RTSP_TRANSPORT_RTP) {1935 } else if (rt->transport == RTSP_TRANSPORT_RTP) {
1934 ret = ff_rtp_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);1936 ret = ff_rtp_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
1937 if (rtsp_st->feedback) {
1938 AVIOContext *pb = NULL;
1939 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_CUSTOM)
1940 pb = s->pb;
1941 ff_rtp_send_rtcp_feedback(rtsp_st->transport_priv, rtsp_st->rtp_handle, pb);
1942 }
1935 if (ret < 0) {1943 if (ret < 0) {
1936 /* Either bad packet, or a RTCP packet. Check if the1944 /* Either bad packet, or a RTCP packet. Check if the
1937 * first_rtcp_ntp_time field was initialized. */1945 * first_rtcp_ntp_time field was initialized. */
libavformat/rtsp.h+3−0
@@ -437,6 +437,9 @@ typedef struct RTSPStream { · 436 unmodified lines
437 /** private data associated with the dynamic protocol */437 /** private data associated with the dynamic protocol */
438 PayloadContext *dynamic_protocol_context;438 PayloadContext *dynamic_protocol_context;
439 //@}439 //@}
440
441 /** Enable sending RTCP feedback messages according to RFC 4585 */
442 int feedback;
440} RTSPStream;443} RTSPStream;
441 444
442void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,445void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
libavformat/version.h+1−1
@@ -31,7 +31,7 @@ · 30 unmodified lines
31 31
32#define LIBAVFORMAT_VERSION_MAJOR 5432#define LIBAVFORMAT_VERSION_MAJOR 54
33#define LIBAVFORMAT_VERSION_MINOR 5933#define LIBAVFORMAT_VERSION_MINOR 59
34#define LIBAVFORMAT_VERSION_MICRO 10634#define LIBAVFORMAT_VERSION_MICRO 107
35 35
36#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \36#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
37 LIBAVFORMAT_VERSION_MINOR, \37 LIBAVFORMAT_VERSION_MINOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t