~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to modules/stream_out/rtcp.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * rtcp.c: RTCP stream output support
 
3
 *****************************************************************************
 
4
 * Copyright © 2007 Rémi Denis-Courmont
 
5
 * $Id$
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
20
 *****************************************************************************/
 
21
 
 
22
/*****************************************************************************
 
23
 * Preamble
 
24
 *****************************************************************************/
 
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
# include "config.h"
 
28
#endif
 
29
 
 
30
#include <vlc_common.h>
 
31
#include <vlc_block.h>
 
32
 
 
33
#include <vlc_network.h>
 
34
#include <vlc_sout.h>
 
35
#include "rtp.h"
 
36
 
 
37
#include <assert.h>
 
38
 
 
39
/*
 
40
 * NOTE on RTCP implementation:
 
41
 * - there is a single sender (us), no conferencing here! => n = sender = 1,
 
42
 * - as such we need not bother to include Receiver Reports,
 
43
 * - in unicast case, there is a single receiver => members = 1 + 1 = 2,
 
44
 *   and obviously n > 25% of members,
 
45
 * - in multicast case, we do not want to maintain the number of receivers
 
46
 *   and we assume it is big (i.e. than 3) because that's what broadcasting is
 
47
 *   all about,
 
48
 * - it is assumed we_sent = true (could be wrong), since we are THE sender,
 
49
 * - we always send SR + SDES, while running,
 
50
 * - FIXME: we do not implement separate rate limiting for SDES,
 
51
 * - we do not implement any profile-specific extensions for the time being.
 
52
 */
 
53
struct rtcp_sender_t
 
54
{
 
55
    size_t   length;  /* RTCP packet length */
 
56
    uint8_t  payload[28 + 8 + (2 * 257) + 8];
 
57
    int      handle;  /* RTCP socket handler */
 
58
 
 
59
    uint32_t packets; /* RTP packets sent */
 
60
    uint32_t bytes;   /* RTP bytes sent */
 
61
    unsigned counter; /* RTP packets sent since last RTCP packet */
 
62
};
 
63
 
 
64
 
 
65
rtcp_sender_t *OpenRTCP (vlc_object_t *obj, int rtp_fd, int proto,
 
66
                         bool mux)
 
67
{
 
68
    rtcp_sender_t *rtcp;
 
69
    uint8_t *ptr;
 
70
    int fd;
 
71
    char src[NI_MAXNUMERICHOST];
 
72
    int sport;
 
73
 
 
74
    if (net_GetSockAddress (rtp_fd, src, &sport))
 
75
        return NULL;
 
76
 
 
77
    if (mux)
 
78
    {
 
79
        /* RTP/RTCP mux: duplicate the socket */
 
80
#ifndef WIN32
 
81
        fd = dup (rtp_fd);
 
82
#else
 
83
        WSAPROTOCOL_INFO info;
 
84
        WSADuplicateSocket (rtp_fd, GetCurrentProcessId (), &info);
 
85
        fd = WSASocket (info.iAddressFamily, info.iSocketType, info.iProtocol,
 
86
                        &info, 0, 0);
 
87
#endif
 
88
    }
 
89
    else
 
90
    {
 
91
        /* RTCP on a separate port */
 
92
        char dst[NI_MAXNUMERICHOST];
 
93
        int dport;
 
94
 
 
95
        if (net_GetPeerAddress (rtp_fd, dst, &dport))
 
96
            return NULL;
 
97
 
 
98
        sport++;
 
99
        dport++;
 
100
 
 
101
        fd = net_OpenDgram (obj, src, sport, dst, dport, AF_UNSPEC, proto);
 
102
    }
 
103
 
 
104
    if (fd == -1)
 
105
        return NULL;
 
106
 
 
107
    rtcp = malloc (sizeof (*rtcp));
 
108
    if (rtcp == NULL)
 
109
    {
 
110
        net_Close (fd);
 
111
        return NULL;
 
112
    }
 
113
 
 
114
    rtcp->handle = fd;
 
115
    rtcp->bytes = rtcp->packets = rtcp->counter = 0;
 
116
 
 
117
    ptr = (uint8_t *)strchr (src, '%');
 
118
    if (ptr != NULL)
 
119
        *ptr = '\0'; /* remove scope ID frop IPv6 addresses */
 
120
 
 
121
    ptr = rtcp->payload;
 
122
 
 
123
    /* Sender report */
 
124
    ptr[0] = 2 << 6; /* V = 2, P = RC = 0 */
 
125
    ptr[1] = 200; /* payload type: Sender Report */
 
126
    SetWBE (ptr + 2, 6); /* length = 6 (7 double words) */
 
127
    memset (ptr + 4, 0, 4); /* SSRC unknown yet */
 
128
    SetQWBE (ptr + 8, NTPtime64 ());
 
129
    memset (ptr + 16, 0, 12); /* timestamp and counters */
 
130
    ptr += 28;
 
131
 
 
132
    /* Source description */
 
133
    uint8_t *sdes = ptr;
 
134
    ptr[0] = (2 << 6) | 1; /* V = 2, P = 0, SC = 1 */
 
135
    ptr[1] = 202; /* payload type: Source Description */
 
136
    uint8_t *lenptr = ptr + 2;
 
137
    memset (ptr + 4, 0, 4); /* SSRC unknown yet */
 
138
    ptr += 8;
 
139
 
 
140
    ptr[0] = 1; /* CNAME - mandatory */
 
141
    assert (NI_MAXNUMERICHOST <= 256);
 
142
    ptr[1] = strlen (src);
 
143
    memcpy (ptr + 2, src, ptr[1]);
 
144
    ptr += ptr[1] + 2;
 
145
 
 
146
    static const char tool[] = PACKAGE_STRING;
 
147
    ptr[0] = 6; /* TOOL */
 
148
    ptr[1] = (sizeof (tool) > 256) ? 255 : (sizeof (tool) - 1);
 
149
    memcpy (ptr + 2, tool, ptr[1]);
 
150
    ptr += ptr[1] + 2;
 
151
 
 
152
    while ((ptr - sdes) & 3) /* 32-bits padding */
 
153
        *ptr++ = 0;
 
154
    SetWBE (lenptr, (ptr - sdes - 1) >> 2);
 
155
 
 
156
    rtcp->length = ptr - rtcp->payload;
 
157
    return rtcp;
 
158
}
 
159
 
 
160
 
 
161
void CloseRTCP (rtcp_sender_t *rtcp)
 
162
{
 
163
    if (rtcp == NULL)
 
164
        return;
 
165
 
 
166
    uint8_t *ptr = rtcp->payload;
 
167
    uint64_t now64 = NTPtime64 ();
 
168
    SetQWBE (ptr + 8, now64); /* Update the Sender Report timestamp */
 
169
 
 
170
    /* Bye */
 
171
    ptr += rtcp->length;
 
172
    ptr[0] = (2 << 6) | 1; /* V = 2, P = 0, SC = 1 */
 
173
    ptr[1] = 203; /* payload type: Bye */
 
174
    SetWBE (ptr + 2, 1);
 
175
    memcpy (ptr + 4, rtcp->payload + 4, 4); /* Copy SSRC from Sender Report */
 
176
    rtcp->length += 8;
 
177
 
 
178
    /* We are THE sender, so we are more important than anybody else, so
 
179
     * we can afford not to check bandwidth constraints here. */
 
180
    send (rtcp->handle, rtcp->payload, rtcp->length, 0);
 
181
    net_Close (rtcp->handle);
 
182
    free (rtcp);
 
183
}
 
184
 
 
185
 
 
186
void SendRTCP (rtcp_sender_t *restrict rtcp, const block_t *rtp)
 
187
{
 
188
    if ((rtcp == NULL) /* RTCP sender off */
 
189
     || (rtp->i_buffer < 12)) /* too short RTP packet */
 
190
        return;
 
191
 
 
192
    /* Updates statistics */
 
193
    rtcp->packets++;
 
194
    rtcp->bytes += rtp->i_buffer;
 
195
    rtcp->counter += rtp->i_buffer;
 
196
 
 
197
    /* 1.25% rate limit */
 
198
    if ((rtcp->counter / 80) < rtcp->length)
 
199
        return;
 
200
 
 
201
    uint8_t *ptr = rtcp->payload;
 
202
    uint32_t last = GetDWBE (ptr + 8); // last RTCP SR send time
 
203
    uint64_t now64 = NTPtime64 ();
 
204
    if ((now64 >> 32) < (last + 5))
 
205
        return; // no more than one SR every 5 seconds
 
206
 
 
207
    memcpy (ptr + 4, rtp->p_buffer + 8, 4); /* SR SSRC */
 
208
    SetQWBE (ptr + 8, now64);
 
209
    memcpy (ptr + 16, rtp->p_buffer + 4, 4); /* RTP timestamp */
 
210
    SetDWBE (ptr + 20, rtcp->packets);
 
211
    SetDWBE (ptr + 24, rtcp->bytes);
 
212
    memcpy (ptr + 28 + 4, rtp->p_buffer + 8, 4); /* SDES SSRC */
 
213
 
 
214
    if (send (rtcp->handle, ptr, rtcp->length, 0) == (ssize_t)rtcp->length)
 
215
        rtcp->counter = 0;
 
216
}