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

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

o (critical issue fixed)

when we are in CC mode, we shouldn't call Transmitter::flush() at the encoder
side - see H261Encoder::encode() that this method calls "tx_->flush()" which
forces to transmit packets in the queue.

--> needed to implement a macro to block calling Transmitter::flush() when CC is

active

  • 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                // record the local pb pointer to the global location
236                pb_ = pb;
237        }
238        // CC is not active, so just go for the normal operation
239        else {
240                if (!busy_) {
241                        double delay = txtime(pb);
242                        nextpkttime_ = gettimeofday_secs() + delay;
243                        output(pb);
244                        /*
245                         * emulate a transmit interrupt --
246                         * assume we will have more to send.
247                         */
248                        msched(int(delay * 1e-3));
249                        busy_ = 1;
250                } else {
251                        if (head_ != 0) {
252                                tail_->next = pb;
253                                tail_ = pb;
254                        } else
255                                tail_ = head_ = pb;
256                        pb->next = 0;
257                }
258        } // if (is_cc_active_)
259}
260
261void Transmitter::timeout()
262{
263        double now = gettimeofday_secs();
264        for (;;) {
265                pktbuf* p = head_;
266                if (p != 0) {
267                        head_ = p->next;
268                        nextpkttime_ += txtime(p);
269                        output(p);
270                        int ms = int(1e-3 * (nextpkttime_ - now));
271                        /* make sure we will wait more than 10ms */
272                        if (ms > 1000) {
273                                msched(ms);
274                                return;
275                        }
276                } else {
277                        busy_ = 0;
278                        break;
279                }
280        }
281}
282
283void Transmitter::flush()
284{
285        if (!is_cc_on()) {
286                if (busy_) {
287                        busy_ = 0;
288                        cancel();
289                }
290
291                pktbuf* p = head_;
292                while (p != 0) {
293                        pktbuf* n = p->next;
294                        output(p);
295                        p = n;
296                }
297                head_ = 0;
298        }
299}
300
301void Transmitter::output(pktbuf* pb)
302{
303        //if (dumpfd_ >= 0)
304        //      dump(dumpfd_, pb->iov, mh_.msg_iovlen);
305//dprintf("layer: %d \n",pb->layer);
306        transmit(pb);
307        loopback(pb);
308//      pb->release() is called by decoder in loopback;
309}
310
311/*void Transmitter::release(pktbuf* pb)
312{
313        pb->next = freehdrs_;
314        freehdrs_ = pb;
315        buffer* p = pb->buf;
316        if (p != 0) {
317                p->next = freebufs_;
318                freebufs_ = p;
319        }
320}
321*/
Note: See TracBrowser for help on using the browser.