[Ffmpeg-devel] [PATCH proposal] RTCP receiver report
Ryan Martell
rdm4
Mon Oct 30 23:36:07 CET 2006
That's pretty close to the patch here.
The problem that I have is that url_write() is returning -2, which is
an error. I don't know whether the packet is going across the wire
(haven't looked that far into it yet). The main thing is that the
url_open() is called with RDWR, which is true in both of these patches.
I'll just have to investigate further...
Thanks, Fran?ois.
-Ryan
On Oct 30, 2006, at 3:51 PM, Fran?ois Revol wrote:
> For the record, and since I don't have much time atm; here is the last
> version of my own patch for this, hope it helps.
> It worked very well for me in linux; almost in BeOS but because the
> NIC
> driver was loosing packets.
> I think I posted it already, and the patch I saw included parts, but
> just in case...
>
> Fran?ois.
> Index: libavformat/rtp.c
> ===================================================================
> --- libavformat/rtp.c (revision 6387)
> +++ libavformat/rtp.c (working copy)
> @@ -197,6 +197,9 @@
> MpegTSContext *ts; /* only used for MP2T payloads */
> int read_buf_index;
> int read_buf_size;
> + /* used to send back RTCP RR */
> + URLContext *rtp_ctx;
> + char hostname[16];
>
> /* rtcp sender statistics receive */
> int64_t last_rtcp_ntp_time;
> @@ -265,12 +268,78 @@
> return 0;
> }
>
> + /**
> + * some rtp servers assume client is dead if they don't hear from
> them...
> + * so we send a Receiver Report to the provided ByteIO context
> + * (we don't have access to the rtcp handle from here)
> + */
> +int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count)
> +{
> + ByteIOContext pb;
> + uint8_t *buf;
> + int len;
> + int rtcp_bytes;
> +
> + if (!s->rtp_ctx || (count < 1))
> + return -1;
> +
> + /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
> + s->octet_count += count;
> + rtcp_bytes = ((s->octet_count - s->last_octet_count) *
> RTCP_TX_RATIO_NUM) /
> + RTCP_TX_RATIO_DEN;
> + rtcp_bytes /= 50; // mmu_man: that's enough for me... VLC
> sends much less btw !?
> + if (rtcp_bytes < 28)
> + return -1;
> + s->last_octet_count = s->octet_count;
> +
> + if (url_open_dyn_buf(&pb) < 0)
> + return -1;
> +
> + // Receiver Report
> + put_byte(&pb, (RTP_VERSION << 6) + 1); /* 1 report block */
> + put_byte(&pb, 201);
> + put_be16(&pb, 6); /* length in words - 1 */
> + //put_be32(&pb, s->ssrc); // our own SSRC
> + put_be32(&pb, s->ssrc); // XXX: should be the server's here!
> + // some placeholders we should really fill...
> + put_be32(&pb, ((0 << 24) | (0 & 0x0ffffff))); /* 0% lost,
> total 0 lost */
> + put_be32(&pb, (0 << 16) | s->seq);
> + put_be32(&pb, 0x68); /* jitter */
> + put_be32(&pb, -1); /* last SR timestamp */
> + put_be32(&pb, 1); /* delay since last SR */
> +
> + // CNAME
> + put_byte(&pb, (RTP_VERSION << 6) + 1); /* 1 report block */
> + put_byte(&pb, 202);
> + len = strlen(s->hostname);
> + put_be16(&pb, (6 + len + 3) / 4); /* length in words - 1 */
> + put_be32(&pb, s->ssrc);
> + put_byte(&pb, 0x01);
> + put_byte(&pb, len);
> + put_buffer(&pb, s->hostname, len);
> + // padding
> + for (len = (6 + len) % 4; len % 4; len++) {
> + put_byte(&pb, 0);
> + }
> +
> + put_flush_packet(&pb);
> + len = url_close_dyn_buf(&pb, &buf);
> + if ((len > 0) && buf) {
> +#if defined(DEBUG)
> + printf("sending %d bytes of RR\n", len);
> +#endif
> + url_write(s->rtp_ctx, buf, len);
> + av_free(buf);
> + }
> + return 0;
> +}
> +
> /**
> * open a new RTP parse context for stream 'st'. 'st' can be NULL for
> * MPEG2TS streams to indicate that they should be demuxed inside the
> * rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned)
> */
> -RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st,
> int payload_type, rtp_payload_data_t *rtp_payload_data)
> +RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st,
> URLContext *rtpc, int payload_type, rtp_payload_data_t
> *rtp_payload_data)
> {
> RTPDemuxContext *s;
>
> @@ -302,6 +371,9 @@
> break;
> }
> }
> + // needed to send back RTCP RR in RTSP sessions
> + s->rtp_ctx = rtpc;
> + gethostname(s->hostname, sizeof(s->hostname));
> return s;
> }
>
> Index: libavformat/rtp.h
> ===================================================================
> --- libavformat/rtp.h (revision 6387)
> +++ libavformat/rtp.h (working copy)
> @@ -28,10 +28,11 @@
>
> typedef struct RTPDemuxContext RTPDemuxContext;
> typedef struct rtp_payload_data_s rtp_payload_data_s;
> -RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st,
> int payload_type, rtp_payload_data_s *rtp_payload_data);
> +RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st,
> URLContext *rtpc, int payload_type, rtp_payload_data_s
> *rtp_payload_data);
> int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
> const uint8_t *buf, int len);
> void rtp_parse_close(RTPDemuxContext *s);
> +int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count);
>
> extern AVOutputFormat rtp_muxer;
> extern AVInputFormat rtp_demuxer;
> Index: libavformat/rtsp.c
> ===================================================================
> --- libavformat/rtsp.c (revision 6387)
> +++ libavformat/rtsp.c (working copy)
> @@ -31,6 +31,8 @@
> //#define DEBUG
> //#define DEBUG_RTP_TCP
>
> +#define USERAGENT "FFMpeg libavformat " LIBAVFORMAT_IDENT
> +
> enum RTSPClientState {
> RTSP_STATE_IDLE,
> RTSP_STATE_PLAYING,
> @@ -702,6 +704,8 @@
> pstrcpy(buf, sizeof(buf), cmd);
> snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
> pstrcat(buf, sizeof(buf), buf1);
> + snprintf(buf1, sizeof(buf1), "User-Agent: %s\r\n", USERAGENT);
> + pstrcat(buf, sizeof(buf), buf1);
> if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
> snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt-
> >session_id);
> pstrcat(buf, sizeof(buf), buf1);
> @@ -863,7 +867,7 @@
> if (RTSP_RTP_PORT_MIN != 0) {
> while(j <= RTSP_RTP_PORT_MAX) {
> snprintf(buf, sizeof(buf), "rtp://?localport=%
> d", j);
> - if (url_open(&rtsp_st->rtp_handle, buf,
> URL_RDONLY) == 0) {
> + if (url_open(&rtsp_st->rtp_handle, buf,
> URL_RDWR) == 0) {
> j += 2; /* we will use two port by rtp
> stream (rtp and rtcp) */
> goto rtp_opened;
> }
> @@ -960,7 +964,7 @@
> host,
> reply->transports[0].server_port_min,
> ttl);
> - if (url_open(&rtsp_st->rtp_handle, url,
> URL_RDONLY) < 0) {
> + if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR)
> < 0) {
> err = AVERROR_INVALIDDATA;
> goto fail;
> }
> @@ -973,7 +977,7 @@
> st = s->streams[rtsp_st->stream_index];
> if (!st)
> s->ctx_flags |= AVFMTCTX_NOHEADER;
> - rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st-
> >sdp_payload_type, &rtsp_st->rtp_payload_data);
> + rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st-
> >rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
>
> if (!rtsp_st->rtp_ctx) {
> err = AVERROR_NOMEM;
> @@ -1131,6 +1135,8 @@
> case RTSP_PROTOCOL_RTP_UDP:
> case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
> len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
> + if (rtsp_st->rtp_ctx)
> + rtp_check_and_send_back_rr(rtsp_st->rtp_ctx, len);
> break;
> }
> if (len < 0)
> @@ -1310,7 +1316,7 @@
> inet_ntoa(rtsp_st->sdp_ip),
> rtsp_st->sdp_port,
> rtsp_st->sdp_ttl);
> - if (url_open(&rtsp_st->rtp_handle, url, URL_RDONLY) < 0) {
> + if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
> err = AVERROR_INVALIDDATA;
> goto fail;
> }
> @@ -1320,7 +1326,7 @@
> st = s->streams[rtsp_st->stream_index];
> if (!st)
> s->ctx_flags |= AVFMTCTX_NOHEADER;
> - rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st-
> >sdp_payload_type, &rtsp_st->rtp_payload_data);
> + rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st-
> >rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
> if (!rtsp_st->rtp_ctx) {
> err = AVERROR_NOMEM;
> goto fail;
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at mplayerhq.hu
> http://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-devel
More information about the ffmpeg-devel
mailing list