[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