~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Open Mash Cross Reference
mash/archive/rtp-play.cc

Component: ~ [ mash ] ~ [ apps ] ~ [ gsm ] ~ [ lib ] ~ [ otcl ] ~ [ srm ] ~ [ tcl8.3 ] ~ [ tclcl ] ~ [ tk8.3 ] ~ [ tutorials ] ~

  1 /*
  2  * rtp-play.cc --
  3  *
  4  *      RTP Play for archive streams
  5  *
  6  * Copyright (c) 1997-2002 The Regents of the University of California.
  7  * All rights reserved.
  8  *
  9  * Redistribution and use in source and binary forms, with or without
 10  * modification, are permitted provided that the following conditions are met:
 11  *
 12  * A. Redistributions of source code must retain the above copyright notice,
 13  *    this list of conditions and the following disclaimer.
 14  * B. Redistributions in binary form must reproduce the above copyright notice,
 15  *    this list of conditions and the following disclaimer in the documentation
 16  *    and/or other materials provided with the distribution.
 17  * C. Neither the names of the copyright holders nor the names of its
 18  *    contributors may be used to endorse or promote products derived from this
 19  *    software without specific prior written permission.
 20  *
 21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
 22  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 23  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 31  * POSSIBILITY OF SUCH DAMAGE.
 32  */
 33 
 34 #include <tclcl.h>
 35 #include "net/net.h"
 36 #include "rtp/rtp.h"
 37 #include "misc/mtrace.h"
 38 #include "archive/archive-stream.h"
 39 #include "archive/rtp-play.h"
 40 #include "misc/nethost.h"
 41 #include "tclcl-mappings.h"
 42 
 43 
 44 
 45 
 46 DEFINE_OTCL_CLASS(RTPPlaybackStream, "ArchiveStream/Play/RTP") {
 47         INSTPROC(buffer_pool);
 48         INSTPROC(attach_agent);
 49         INSTPROC(header_info);
 50 }
 51 
 52 DEFINE_OTCL_CLASS(RTPPlayRcvr, "Module/RTPPlay") {
 53 }
 54 
 55 
 56 RTPPlaybackStream::RTPPlaybackStream()
 57         : PlaybackStream(), startTS_(0), endTS_(0), dnet_(NULL), cnet_(NULL),
 58           free_(NULL), eof_(0), skipctrl_(1), converter_(0.0),
 59           firstTime_(TRUE), bufferPool_(NULL), cs_(0), firstseq_(0),
 60           p_(0), lastp_(0), agent_(NULL), lastNotify_(0.0)
 61 {
 62 }
 63 
 64 RTPPlaybackStream::~RTPPlaybackStream() {
 65         printf("In rtp-play.cc destroy\n");
 66         agent_->send_bye();
 67 }
 68 
 69 
 70 int
 71 RTPPlaybackStream::header_info(int argc, const char * const *argv)
 72 {
 73         Tcl &tcl = Tcl::instance();
 74         int returnValue;
 75         FileHeader hdrNet;
 76         RTPprivatehdr phdrNet;
 77         const char *hdrArray;
 78 
 79         double last_recv;
 80         u_int32_t last_rtp;
 81         double first_recv, new_scale;
 82 
 83         int modend, endpos;
 84 
 85         DataFile* file = DataFile_();
 86         IndexFile* ifile = IndexFile_();
 87 
 88         BEGIN_PARSE_ARGS(argc, argv);
 89         ARG(hdrArray);
 90         END_PARSE_ARGS;
 91 
 92         if (file->IsOpen()==FALSE) {
 93                 tcl.resultf("file not open");
 94                 goto error;
 95         }
 96 
 97         returnValue = file->Read(&hdrNet, (u_char *)&phdrNet, sizeof(RTPprivatehdr));
 98 
 99         net2host(hdrNet, hdr_);
100         net2host(phdrNet, phdr_);
101         MTrace(trcArchive|trcVerbose, ("%s Default Scale = %lu\n",hdr_.name,  phdr_.scale));
102 
103         // Calculate scale, using recv timestamps
104         IndexRecord iNet, iHost;
105 
106         if (ifile->Seek(0, SEEK_END)==TCL_ERROR)
107                 return TCL_ERROR;
108         endpos = ifile->Tell();
109         // This is only necessary in pathological cases, where the disk filled up, etc
110         modend = ((endpos - sizeof(FileHeader)) % sizeof(IndexRecord));
111         if (modend != 0) {
112                 MTrace(trcArchive, ("Wrong Size, truncing"));
113                 endpos = endpos - modend;
114         }
115 
116         if (ifile->Seek(endpos - sizeof(IndexRecord), SEEK_SET)==TCL_ERROR)
117                 return TCL_ERROR;
118 
119 
120         //if (ifile->Seek(-1*((int)sizeof(IndexRecord)), SEEK_END)==TCL_ERROR)  {
121         //return TCL_ERROR;
122         //}
123 
124         if (ifile->Read(&iNet)==TCL_ERROR) {
125                         return TCL_ERROR;
126         }
127         net2host(iNet, iHost);
128 
129         last_rtp = logical2rtp(iHost.sentTS_sec, iHost.sentTS_usec, phdr_.scale, phdr_.ref_rtp, phdr_.ref_tv_sec, phdr_.ref_tv_usec);
130         last_recv = iHost.recvTS_sec + iHost.recvTS_usec/1000000.0;
131         first_recv = phdr_.ref_tv_sec + phdr_.ref_tv_usec/1000000.0;
132         new_scale = (last_rtp - phdr_.ref_rtp) / (last_recv - first_recv);
133 /*FIXME*/
134 if (new_scale > 7800 && new_scale < 8200) {
135         //printf("warning mccanne hack\n");
136         new_scale = 8000;
137 }
138         MTrace(trcArchive|trcVerbose, ("New Scale = %g\n", new_scale));
139         phdr_.scale = (int) new_scale;
140         //printf("first_recv=%g last_recv=%g last_rtp=%u first_rtp=%g\n", first_recv, last_recv, last_rtp, phdr_.ref_rtp);
141         //
142 
143         char c_ssrc[16];
144         sprintf(c_ssrc, "%u", host2net(phdr_.ssrc));
145 
146         if (Tcl_SetVar2(tcl.interp(), (char*)hdrArray, "cname",
147                         hdr_.cname, TCL_LEAVE_ERR_MSG)==NULL) {
148                 tcl.resultf("\nwhile writing to array '%s'", hdrArray);
149                 goto error;
150         }
151         if (Tcl_SetVar2(tcl.interp(), (char*)hdrArray, "name",
152                         hdr_.name, TCL_LEAVE_ERR_MSG)==NULL) {
153                 tcl.resultf("\nwhile writing to array '%s'", hdrArray);
154                 goto error;
155         }
156         if (Tcl_SetVar2(tcl.interp(), (char*)hdrArray, "email",
157                         phdr_.email, TCL_LEAVE_ERR_MSG)==NULL) {
158                 tcl.resultf("\nwhile writing to array '%s'", hdrArray);
159                 goto error;
160         }
161         if (Tcl_SetVar2(tcl.interp(), (char*)hdrArray, "ssrc",
162                         c_ssrc, TCL_LEAVE_ERR_MSG)==NULL) {
163                 tcl.resultf("\nwhile writing to array '%s'", hdrArray);
164                 goto error;
165         }
166         if (Tcl_SetVar2(tcl.interp(), (char*)hdrArray, "phone",
167                         phdr_.phone, TCL_LEAVE_ERR_MSG)==NULL) {
168                 tcl.resultf("\nwhile writing to array '%s'", hdrArray);
169                 goto error;
170         }
171         if (Tcl_SetVar2(tcl.interp(), (char*)hdrArray, "loc",
172                         phdr_.loc, TCL_LEAVE_ERR_MSG)==NULL) {
173                 tcl.resultf("\nwhile writing to array '%s'", hdrArray);
174                 goto error;
175         }
176         if (Tcl_SetVar2(tcl.interp(), (char*)hdrArray, "tool",
177                         phdr_.tool, TCL_LEAVE_ERR_MSG)==NULL) {
178                 tcl.resultf("\nwhile writing to array '%s'", hdrArray);
179                 goto error;
180         }
181         tcl.resultf("");
182         return TCL_OK;
183 
184 error:
185         tcl.add_errorf("\ninvoked from within RTPPlaybackStream::Header_Info()");
186         return TCL_ERROR;
187 }
188 
189 
190 
191 
192 int
193 RTPPlaybackStream::attach_agent(int argc, const char * const *argv)
194 {
195         TclObject* agent;
196 
197         BEGIN_PARSE_ARGS(argc, argv);
198         ARG(agent);
199         END_PARSE_ARGS;
200 
201         agent_=(RTPPlaySession *)agent;
202         return TCL_OK;
203 }
204 
205 int
206 RTPPlaybackStream::buffer_pool(int argc, const char * const *argv)
207 {
208         TclObject* bufferPool;
209 
210         BEGIN_PARSE_ARGS(argc, argv);
211         ARG(bufferPool);
212         END_PARSE_ARGS;
213 
214         bufferPool_=(BufferPool *)bufferPool;
215 
216         /*FIXME*/
217         int npack = 64;/*FIXME*/
218         for (int i = 0; i < npack; ++i) {
219                 RTPPacket* p = new RTPPacket;
220                 p->buf=bufferPool_->alloc();
221                 free(p);
222         }
223         return TCL_OK;
224 }
225 
226 
227 #if OLD
228 int
229 RTPPlaybackStream::Datanet(int argc, const char * const *argv)
230 {
231         TclObject* datanet;
232 
233         BEGIN_PARSE_ARGS(argc, argv);
234         ARG(datanet);
235         END_PARSE_ARGS;
236 
237         dnet_=(Network *)datanet;
238         return TCL_OK;
239 }
240 
241 int
242 RTPPlaybackStream::Ctrlnet(int argc, const char * const *argv)
243 {
244         TclObject* ctrlnet;
245 
246         BEGIN_PARSE_ARGS(argc, argv);
247         ARG(ctrlnet);
248         END_PARSE_ARGS;
249 
250         cnet_=(Network *)ctrlnet;
251         return TCL_OK;
252 }
253 #endif
254 
255 
256 void
257 RTPPlaybackStream::Clip(timeval start, timeval end)
258 {
259         startTS_= logical2rtp(start, phdr_.scale, phdr_.ref_rtp,
260                                 phdr_.ref_tv_sec, phdr_.ref_tv_usec);
261         endTS_ = logical2rtp(end, phdr_.scale, phdr_.ref_rtp,
262                                 phdr_.ref_tv_sec, phdr_.ref_tv_usec);
263         //startTS_ = logical2rtp(start.tv_sec, start.tv_usec, converter_);
264         //endTS_ = logical2rtp(end.tv_sec, end.tv_usec, converter_);
265 }
266 
267 
268 
269 /*
270  * add packet p to the queue of waiting packets for this
271  * source.  The queue is ordered by seqno.
272  */
273 void
274 RTPPlaybackStream::addpacket(RTPPacket* p, u_int ts, u_int seqno)
275 {
276         //MTrace(trcArchive, ("addpacket %u %u",ts, seqno));
277 
278         /* convert the seqno to 32 bits */
279         if (p->type) {  // if it's a control packet
280                 MTrace(trcArchive|trcVerbose, ("addpacket control pkt"));
281                 seqno = firstseq_;
282                 if (lastp_) {
283                         seqno += lastp_->seq;
284                         ts = lastp_->its;
285                 }
286         } else {  // Data packet
287                 register int c = cs_;
288                 register int d = seqno - c;
289                 if (d < -1024 || d > 1024) {
290                         cs_ = seqno;
291                         if (seqno < 512 && c > 0x10000-512) {
292                                 /*
293                                  * seq no. wrapped - subtract 64k from firstseq to
294                                  * account for it.
295                                  */
296                                 firstseq_ -= 0x10000;
297                         } else {
298                                 /*
299                                  * the seq. no made a very large
300                                  * jump.  assume that the other
301                                  * side restarted without telling
302                                  * us about it so just re-sync
303                                  * (i.e., pretend this was the
304                                  * first packet).
305                                  */
306                                 firstseq_ = seqno - 1;
307                         }
308                 } else if (d > 0) {
309                         /*
310                          * d <= 0 means duplicate or reordered packet so
311                          * don't move cs_
312                          */
313                         cs_ = seqno;
314                 }
315         }
316         seqno -= firstseq_;
317         p->seq = seqno;
318         MTrace(trcArchive, ("addpacket %u", seqno));
319 
320         p->its=ts;
321         //MTrace(trcArchive, ("addpacket %u",ts));
322         /*
323          * find where in the queue to insert this packet.
324          * the usual case of inserting at the tail is special cased
325          * for performance reasons.
326          */
327         if (lastp_ == 0) {
328                 lastp_ = p;
329                 p_ = p;
330                 p->next = 0;
331         } else if (lastp_->its < p->its ||
332                    (p->its == lastp_->its && int(seqno - lastp_->seq) > 0)) {
333                 lastp_->next = p;
334                 lastp_ = p;
335                 p->next = 0;
336         } else if (p->its < p_->its ||
337                    (p->its == p_->its && int(seqno - p_->seq) <= 0)) {
338                 p->next = p_;
339                 p_ = p;
340         } else {
341                 RTPPacket* np;
342                 for (RTPPacket* lp = p_; (np = lp->next) != 0; lp = np) {
343                         if (p->its < np->its ||
344                             (p->its == np->its && int(seqno - np->seq) <= 0)) {
345                                 lp->next = p;
346                                 p->next = np;
347                                 break;
348                         }
349                 }
350         }
351 }
352 
353 
354 
355 u_int
356 RTPPlaybackStream::ts() const
357 {
358         if (p_ == 0)
359                 /*FIXME*/
360                 return (0);
361 
362         return (p_->its);
363 }
364 
365 RTPPacket*
366 RTPPlaybackStream::getpkt(u_int now)
367 {
368         RTPPacket* p = p_;
369         //MTrace(trcArchive, ("getpkt %f %f %d", p->ts, ts));
370         if (p && ((int)(p->its - now) <= 0 || now == 0)) {
371                 RTPPacket* np = p->next;
372                 p_ = np;
373                 if (np == 0)
374                         lastp_ = 0;
375                 return (p);
376         }
377         return (0);
378 }
379 
380 RTPPacket*
381 RTPPlaybackStream::allocate()
382 {
383 
384         RTPPacket* temp = free_;
385         free_ = temp->next;
386         temp->buf = bufferPool_->alloc();
387         return temp;
388 
389 }
390 
391 void
392 RTPPlaybackStream::EmptyBuffs()
393 {
394 
395         RTPPacket *p; RTPPacket *np;
396 
397         p = p_;
398         while (p) {
399                 np=p->next;
400                 free (p);
401                 p=np;
402         }
403         p_=0;
404         lastp_=0;
405 
406 }
407 
408 void
409 RTPPlaybackStream::IterateIndex(int real_endpos) {
410 
411         IndexFile* ifile;
412         DataFile* dfile;
413         IndexRecord iNet, iHost;
414 
415         ifile = IndexFile_();
416         dfile = DataFile_();
417 
418 
419         int curpos = ifile->Tell();
420         while (curpos < real_endpos) {
421                 if (ifile->Read(&iNet)==TCL_ERROR)
422                         return;
423                 net2host(iNet, iHost);
424                 printf("recv-sent = %d \n", iHost.recvTS_sec - iHost.sentTS_sec);
425                 curpos = ifile->Tell();
426         }
427 
428 
429 }
430 
431 
432 Bool
433 RTPPlaybackStream::SeekTime(timeval goal) {
434 
435         IndexFile* ifile;
436         DataFile* dfile;
437         IndexRecord iNet, iHost;
438         int actual_end, endpos;
439 
440 
441         eof_=0;
442 
443         u_int32_t goalsec= (u_int32_t) goal.tv_sec;
444         u_int32_t goalusec= (u_int32_t)goal.tv_usec;
445 
446         ifile = IndexFile_();
447         dfile = DataFile_();
448 
449         if (ifile->Seek(sizeof(FileHeader), SEEK_SET)==TCL_ERROR)
450                 return TCL_ERROR;
451         if (ifile->Read(&iNet)==TCL_ERROR)
452                         return TCL_ERROR;
453         net2host(iNet, iHost);
454         if ((goalsec < iHost.sentTS_sec) || ((goalsec == iHost.sentTS_sec) && (goalusec <= iHost.sentTS_usec))) {
455                 dfile->Seek(sizeof(FileHeader) + sizeof(RTPprivatehdr), SEEK_SET);
456                 return TCL_OK;
457         }
458 
459         int startpos = sizeof(FileHeader);
460 
461         if (ifile->Seek(0, SEEK_END)==TCL_ERROR)
462                 return TCL_ERROR;
463         actual_end = ifile->Tell();
464         endpos = actual_end;
465         // This is only necessary in pathological cases, where the disk filled up, etc
466         int modend = ((endpos - sizeof(FileHeader)) % sizeof(IndexRecord));
467         if (modend != 0) {
468                 MTrace(trcArchive, ("Wrong Size, truncing"));
469                 endpos = endpos - modend;
470         }
471 
472         if (ifile->Seek(endpos - sizeof(IndexRecord), SEEK_SET)==TCL_ERROR)
473                 return TCL_ERROR;
474         //int real_endpos = endpos;
475         if (ifile->Read(&iNet)==TCL_ERROR)
476                         return TCL_ERROR;
477         net2host(iNet, iHost);
478 
479         //ref_end_rec_ = iHost.recvTS_sec + iHost.recvTS_usec/1000000.0;
480 
481         if (goalsec > iHost.sentTS_sec) {
482                 if (dfile->Seek(0,SEEK_END)==TCL_ERROR)
483                         return TCL_ERROR;
484                 MTrace(trcArchive, ("Sought too end"));
485                 return TCL_OK;
486         }
487         if ((goalsec == iHost.sentTS_sec) &&
488             (goalusec >= iHost.sentTS_usec))
489         {
490                 if (dfile->Seek(iHost.filePointer, SEEK_SET)==TCL_ERROR)
491                         return TCL_ERROR;
492                 MTrace(trcArchive, ("Sought too %u",iHost.seqno));
493                 return TCL_OK;
494         }
495         int newpos=((((endpos-startpos)/sizeof(IndexRecord))/2) * sizeof(IndexRecord)) + startpos;
496 
497 
498         int curpos;
499 
500 
501         for (;;) {
502                 if (ifile->Seek(newpos, SEEK_SET)==TCL_ERROR)
503                         return TCL_ERROR;
504                 if (ifile->Read(&iNet)==TCL_ERROR)
505                         return TCL_ERROR;
506                 net2host(iNet, iHost);
507 
508                 if ((goalsec == iHost.sentTS_sec)
509                     && (goalusec == iHost.sentTS_usec)) {
510                         if (dfile->Seek(iHost.filePointer, SEEK_SET)==TCL_ERROR)
511                                 return TCL_ERROR;
512                         MTrace(trcArchive, ("Sought too %u",iHost.seqno));
513 
514 
515                         return TCL_OK;
516                 }
517                 if ((goalsec > iHost.sentTS_sec) || ((goalsec == iHost.sentTS_sec) && (goalusec >= iHost.sentTS_usec))) {
518                         startpos = newpos + sizeof(IndexRecord);
519                         newpos=((((endpos-startpos)/sizeof(IndexRecord))/2) * sizeof(IndexRecord)) + startpos;
520                 }
521                 if ((goalsec < iHost.sentTS_sec) || ((goalsec == iHost.sentTS_sec) && (goalusec <= iHost.sentTS_usec))) {
522                         endpos = newpos;
523                         newpos=((((endpos-startpos)/sizeof(IndexRecord))/2) * sizeof(IndexRecord)) + startpos;
524                         if (newpos == endpos) {
525                                 if (dfile->Seek(iHost.filePointer, SEEK_SET)==TCL_ERROR)
526                                         return TCL_ERROR;
527                                 MTrace(trcArchive, ("Sought too %u",iHost.seqno));
528                                 curpos = ifile->Tell();
529 
530 
531 
532                                 return TCL_OK;
533                         }
534                 }
535         }
536 
537 
538 
539 }
540 
541 
542 void
543 RTPPlaybackStream::LTS_Speed()
544 {
545         PlaybackStream::LTS_Speed();
546 }
547 
548 
549 void
550 RTPPlaybackStream::LTS_Reference()
551 {
552         EmptyBuffs();
553         timeval now = LTS_()->NowLogical();
554         MTrace (trcArchive, ("LTS_Reference %u %u", now.tv_sec, now.tv_usec));
555         if (SeekTime(now)==TCL_ERROR) {
556                 // FIXME: LTS_Reference should have an error-returning mechanism
557                 return;
558         }
559 
560         PlaybackStream::LTS_Reference();
561 }
562 
563 void
564 RTPPlaybackStream::free(RTPPacket* p)
565 {
566         p->next = free_;
567         free_ = p;
568         p->buf->release();
569 }
570 
571 
572 
573 int
574 RTPPlaybackStream::nextpkt(RTPPacket* p)
575 {
576 
577         DataFile *file;
578         struct recordhdr *rh = (recordhdr *) p->buf->data;
579 
580         file = DataFile_();
581         if (firstTime_==TRUE) {
582 
583                 if (file->Seek(file->getHeaderSize(), SEEK_SET)==TCL_ERROR)
584                         return (-1);
585 
586         }
587 
588 
589         // read header (gives us len and type)
590 
591         if (file->Read((unsigned char*)rh, sizeof(recordhdr))==0) {
592                 eof_ = 1;
593                 return (-1);
594         }
595 
596         int len = net2host(rh->len);
597         int type = rh->type;
598 
599         //MTrace(trcArchive, ("nextpkt type %d", type));
600 
601         int amt = len;
602         if (len > MTU - 4) {
603                 /* FIXME packet too big */
604                 for (len -= amt; len > 0; len -= amt) {
605                         amt = len;
606                         if (amt > MTU)
607                                 amt = MTU;
608                         if (file->Read((u_char*) p->buf->data, amt) == 0) {
609                                 eof_ = 1;
610                                 return (-1);
611                         }
612                 }
613                 return (1);
614         }
615 
616         // now read the rtp packet itself; overwrites recordhdr
617         if (file->Read((u_char*) p->buf->data, amt) == 0) {
618                 eof_ = 1;
619                 return (-1);
620         }
621 
622         // assign relevant fields
623         // others in the RTPPacket struct are assigned in
624         // addpacket
625 
626         p->type = type;
627         p->len = amt;
628 
629 
630 
631 
632         return (len);
633 }
634 
635 
636 
637 int
638 RTPPlaybackStream::fillone()
639 {
640 
641         int rval;
642         u_int id, ts, seq;
643 
644 
645         RTPPacket *p = allocate();
646         rval = nextpkt(p);  /* Actually read from disk */
647 
648         if (rval < 0) {
649                 eof_ = 1;
650                 p->next = free_;
651                 free_ = p;
652                 return (rval);
653         }
654 
655         if (rval < 2) {
656                 return (rval);
657         }
658 
659         struct rtphdr *rh = (struct rtphdr *)p->buf->data;
660 
661         // p.type and p.len will have been filled in by nextpkt above
662 
663         switch (p->type) {
664         default:
665                 return (1);
666         case 0:
667                 // DATA packet (RTP)
668 
669                 skipctrl_ = 0;
670                 id = net2host(rh->rh_ssrc);
671                 ts = net2host(rh->rh_ts);
672                 seq = net2host(rh->rh_seqno);
673                 MTrace (trcArchive|trcVerbose,
674                         ("fillone seqno=%u ts=%u", seq, ts));
675 
676                 break;
677 
678         case 0x80:
679                 // CONTROL packet (RTCP)
680                 // Currently, shouldn't get here
681                 // FIX THIS
682                 struct rtcp_compound {
683                         rtcphdr rt;
684                         rtcp_sr sr;
685                 } *th = (rtcp_compound *) p->buf->data;
686                 if (skipctrl_ || (ntohs(th->rt.rh_flags) & 0xff) \
687                     != RTCP_PT_SR) {
688                         /* not a sender report */
689                         return (1);
690                 }
691                 id = net2host(th->rt.rh_ssrc);
692                 ts = net2host(th->sr.sr_ts);
693                 seq = ~0;
694                 break;
695         }
696 
697         if (firstTime_ == TRUE) {
698                 // Move this to nextpkt after we fix ctrl pkts
699                 cs_=seq;
700                 firstseq_=seq;
701                 firstTime_=FALSE;
702         }
703 
704         addpacket(p, ts, seq);  /* Put the packet in the queue */
705         return (0);
706 }
707 
708 
709 int
710 RTPPlaybackStream::IsDone()
711 {
712         if ((p_==0) && (eof_==1)) {
713                 return 1;
714         }
715         return 0;
716 
717 
718         /*if ((eof_ == 0) && (p_ != 0))
719                 return (0);
720 
721         if (p_!=0)
722                 return (0);
723         return (1); */
724 }
725 
726 int
727 RTPPlaybackStream::NextEvent(timeval &logical)
728 {
729 
730         /* fill all free packet buffers with disk data */
731         while (free_ && (fillone() >= 0)) {
732         }
733 
734 
735         if (IsDone()) {
736                 MTrace(trcArchive, ("RTP playback source is done"));
737                 logical.tv_sec = logical.tv_usec = 0;
738                 EmptyBuffs();
739                 return TCL_OK;
740 
741         }
742 
743         u_int dt=ts();
744         if (endTS_ > 0 && dt > endTS_) {
745                 //we are done
746                 MTrace(trcArchive, ("Exceeded ending ts (%lu): %lu",
747                                     (unsigned long) endTS_,
748                                     (unsigned long) dt));
749                 logical.tv_sec = logical.tv_usec = 0;
750                 return TCL_OK;
751         }
752 
753 
754         //set logical to be time when next pkt should play
755         timeval ref;
756         ref.tv_sec = phdr_.ref_tv_sec;
757         ref.tv_usec = phdr_.ref_tv_usec;
758         //FIXME logical time starts at 0!
759         //ref.tv_sec = ref.tv_usec = 0;
760         //ref.tv_usec = 1;//except 0 has special meaning... FIXME
761 
762         logical = rtp2logical(dt, phdr_.scale, phdr_.ref_rtp,
763                                      ref);
764         MTrace(trcArchive|trcVerbose,
765                ("RTP playback source returned logical timeof %u %u.%u %u",
766                 dt, logical.tv_sec, logical.tv_usec, p_->seq));
767         return TCL_OK;
768 
769 }
770 
771 void
772 RTPPlaybackStream::DoEvent()
773 {
774         double now;
775         timeval ts = LTS_()->NowLogical();
776         u_int dts = logical2rtp(ts, phdr_.scale, phdr_.ref_rtp,
777                                 phdr_.ref_tv_sec, phdr_.ref_tv_usec);
778         for (;;) {
779                 RTPPacket *p = getpkt(dts);
780                 if (p == 0)
781                         return;
782 
783                 MTrace(trcArchive, ("Send seq=%d ",p->seq));
784 
785                 p->buf->len = p->len;
786                 p->buf->next = 0; //??
787 
788                 //p->buf->layer = 1;  //Change this when we support layered video
789                 agent_->send(p->buf);
790 
791                 now = tvtof(LTS_()->NowSystem());
792                 if (now - lastNotify_ > 0.25) {
793                         Invokef("notify_observers bytes_sent 0");
794                         lastNotify_ = now;
795                 }
796 
797                 p->next = free_;
798                 free_ = p;
799 
800                 // p->buf is released in transmitter-rtp
801         }
802 }
803 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.