root/vic/branches/cc/rtp/transmitter.cpp @ 4299

Revision 4299, 7.1 KB (checked in by soohyunc, 6 years ago)

removed unnecessary pointer declaration
(pb_ is not used anywhere else)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*-
2 * Copyright (c) 1993-1994 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the Network Research
16 *      Group at Lawrence Berkeley Laboratory.
17 * 4. Neither the name of the University nor of the Laboratory may be used
18 *    to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * $Id$
34 */
35static const char rcsid[] =
36    "@(#) $Header$ (LBL)";
37
38#include <stdio.h>
39#include <stdlib.h>
40#ifndef WIN32
41#include <unistd.h>
42#endif
43#include <errno.h>
44#include <string.h>
45#ifdef WIN32
46//#include <winsock.h>
47#include <io.h>
48#include <sys/stat.h>
49#else
50#include <sys/param.h>
51#include <sys/uio.h>
52#include <netinet/in.h>
53#include <sys/file.h>
54#include <sys/stat.h>
55#endif
56#include "ntp-time.h"
57#include "pktbuf-rtp.h"
58#include "transmitter.h"
59#include "net.h"
60#include "source.h"
61#include "decoder.h"
62#include "vic_tcl.h"
63
64#if defined(sun) && !defined(__svr4__) || (defined(_AIX) && !defined(_AIX41))
65extern "C" writev(int, iovec*, int);
66#endif
67
68//Transmitter::pktbuf* Transmitter::freehdrs_;
69//Transmitter::buffer* Transmitter::freebufs_;
70int Transmitter::nbufs_;
71int Transmitter::nhdrs_;
72
73/*
74 * Sequence number is static so when we change the encoding (which causes
75 * new encoder to be allocated) we don't reset the sequence counter.
76 * Otherwise, receivers will get confused, reset their stats, and generate
77 * odd looking streams of reception reports (i.e., the packet counts will
78 * drop back to 0).
79 */
80u_int16_t Transmitter::seqno_ = 1;
81
82Transmitter::Transmitter() :
83        mtu_(1024),
84        nf_(0),
85        nb_(0),
86        np_(0),
87        kbps_(128),
88        nextpkttime_(0.),
89        busy_(0),
90        head_(0),
91        tail_(0),
92        loop_layer_(1000),
93        loopback_(0),
94        is_cc_active_(1),
95        is_first_(1)
96{
97        memset((char*)&mh_, 0, sizeof(mh_));
98        mh_.msg_iovlen = 2;
99}
100
101/* Return time of day in seconds */
102inline double Transmitter::gettimeofday_secs() const
103{
104        timeval tv;
105        ::gettimeofday(&tv, 0);
106        return (tv.tv_sec + 1e-6 * tv.tv_usec);
107}
108
109void Transmitter::loopback(pktbuf* pb)
110{
111        int layer = pb->layer;
112        rtphdr* rh = (rtphdr*)pb->data;
113        int cc = pb->len;
114        /*
115         * Update statistics.
116         */
117        if (layer >= loop_layer_) {
118                /*XXX*/
119                pb->release();
120                return;
121        }
122        nb_ += cc;
123        ++np_;
124
125        SourceManager& sm = SourceManager::instance();
126        Source* s = sm.localsrc();
127        timeval now = unixtime();
128        Source::Layer& sl = s->layer(pb->layer);
129
130        sl.lts_data(now);
131        s->action();
132        sl.sts_data(rh->rh_ts);
133        sl.np(1);
134        sl.nb(cc);
135        sl.cs((u_int16_t)ntohs(rh->rh_seqno),s);
136
137        int flags = ntohs(rh->rh_flags);
138        if (flags & RTP_M) {
139                ++nf_;
140                sl.nf(1);
141        }
142        int fmt = flags & 0x7f;
143        /*
144         * Handle initialization of loopback decoder
145         * and changes in the stream.
146         */
147        PacketHandler* h = s->handler();
148        if (h == 0)
149                h = s->activate(fmt);
150        else if (s->format() != fmt) {
151                h = s->change_format(fmt);
152        }
153
154        if (s->mute()) {
155                pb->release();
156                return;
157        }
158        h->recv(pb);
159}
160
161int Transmitter::dumpfd_ = -1;
162void Transmitter::dump(int fd)
163{
164        dumpfd_ = fd;
165#define MAGIC "RTPCLIP 1.0"
166        (void)write(fd, MAGIC, sizeof(MAGIC));
167}
168
169/*XXX*/
170#ifdef WIN32
171int writev(int fd, iovec* iov, int iovlen)
172{
173        int len = 0, n;
174        for (int i = 0; i < iovlen; i++) {
175                if ((n = write(fd, iov[i].iov_base, iov[i].iov_len)) == -1) {
176                        perror("writev");
177                        exit(1);
178                }
179                len += n;
180        }
181        return(len);
182}
183#endif
184
185void Transmitter::dump(int fd, iovec* iov, int iovlen) const
186{
187        register int length = 0;
188        for (int i = iovlen; --i >= 0; )
189                length += iov[i].iov_len;
190
191        char cliphdr[4];
192        *(short*)cliphdr = htons(length);
193        cliphdr[2] = 0; /* data packet (i.e., not an rtcp packet) */
194        cliphdr[3] = 0; /* ? */
195
196        (void)write(fd, cliphdr, 4);
197        if (writev(fd, iov, iovlen) < 0) {
198                perror("write");
199                exit(1);
200        }
201}
202
203/*
204 * Time it takes in seconds to send this
205 * packet at the configured bandwidth.
206 */
207double Transmitter::txtime(pktbuf* pb)
208{
209//      int cc = pb->iov[0].iov_len + pb->iov[1].iov_len;
210        int cc = pb->len;
211        return (8 * cc / (1000. * kbps_));
212}
213
214void Transmitter::send(pktbuf* pb)
215{
216        // CC is active, so just follow CC routines
217        // (i.e., not sending packets here)
218        if (is_cc_on()) {
219                // if it is the very first packet, just send it.
220                if(is_first_) {
221                        tfwc_sndr_send(pb);
222                        output(pb);
223                        is_first_ = false;
224                }
225                // if it is not, just queue up the packets.
226                else {
227                        if (head_ != 0) {
228                                tail_->next = pb;
229                                tail_ = pb;
230                        } else
231                                tail_ = head_ = pb;
232                        pb->next = 0;
233                }
234        }
235        // CC is not active, so just go for the normal operation
236        else {
237                if (!busy_) {
238                        double delay = txtime(pb);
239                        nextpkttime_ = gettimeofday_secs() + delay;
240                        output(pb);
241                        /*
242                         * emulate a transmit interrupt --
243                         * assume we will have more to send.
244                         */
245                        msched(int(delay * 1e-3));
246                        busy_ = 1;
247                } else {
248                        if (head_ != 0) {
249                                tail_->next = pb;
250                                tail_ = pb;
251                        } else
252                                tail_ = head_ = pb;
253                        pb->next = 0;
254                }
255        } // if (is_cc_active_)
256}
257
258void Transmitter::timeout()
259{
260        double now = gettimeofday_secs();
261        for (;;) {
262                pktbuf* p = head_;
263                if (p != 0) {
264                        head_ = p->next;
265                        nextpkttime_ += txtime(p);
266                        output(p);
267                        int ms = int(1e-3 * (nextpkttime_ - now));
268                        /* make sure we will wait more than 10ms */
269                        if (ms > 1000) {
270                                msched(ms);
271                                return;
272                        }
273                } else {
274                        busy_ = 0;
275                        break;
276                }
277        }
278}
279
280void Transmitter::flush()
281{
282        if (!is_cc_on()) {
283                if (busy_) {
284                        busy_ = 0;
285                        cancel();
286                }
287
288                pktbuf* p = head_;
289                while (p != 0) {
290                        pktbuf* n = p->next;
291                        output(p);
292                        p = n;
293                }
294                head_ = 0;
295        }
296}
297
298void Transmitter::output(pktbuf* pb)
299{
300        //if (dumpfd_ >= 0)
301        //      dump(dumpfd_, pb->iov, mh_.msg_iovlen);
302//dprintf("layer: %d \n",pb->layer);
303        transmit(pb);
304        loopback(pb);
305//      pb->release() is called by decoder in loopback;
306}
307
308/*void Transmitter::release(pktbuf* pb)
309{
310        pb->next = freehdrs_;
311        freehdrs_ = pb;
312        buffer* p = pb->buf;
313        if (p != 0) {
314                p->next = freebufs_;
315                freebufs_ = p;
316        }
317}
318*/
Note: See TracBrowser for help on using the browser.