Rtp.hpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: Rtp.hpp * 00006 * * 00007 * * 00008 * * 00009 * ITEC institute of the University of Klagenfurt (Austria) * 00010 * http://www.itec.uni-klu.ac.at * 00011 * * 00012 * * 00013 * For more information visit the ViTooKi homepage: * 00014 * http://ViTooKi.sourceforge.net * 00015 * vitooki-user@lists.sourceforge.net * 00016 * vitooki-devel@lists.sourceforge.net * 00017 * * 00018 * This file is part of ViTooKi, a free video toolkit. * 00019 * ViTooKi is free software; you can redistribute it and/or * 00020 * modify it under the terms of the GNU General Public License * 00021 * as published by the Free Software Foundation; either version 2 * 00022 * of the License, or (at your option) any later version. * 00023 * * 00024 * This program is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU General Public License * 00030 * along with this program; if not, write to the Free Software * 00031 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * 00032 * MA 02111-1307, USA. * 00033 * * 00034 ***********************************************************************/ 00035 00036 /*********************************************************************** 00037 * * 00038 * REVISION HISTORY: * 00039 * * 00040 * * 00041 * * 00042 ***********************************************************************/ 00043 00044 #ifndef _MK_RTP_HPP_ 00045 #define _MK_RTP_HPP_ 00046 #ifdef WIN32 00047 #pragma warning(disable:4786) 00048 #endif 00049 00050 #include "VMutex.hpp" 00051 00052 #include "IO.hpp" 00053 #include "ESInfo.hpp" 00054 #include "adaptors/GlobalTimer.hpp" 00055 #include "net/PortGenerator.hpp" 00056 #ifdef WINCE 00057 #include "3rdparty/commonucl/rtp.h" // UCL library 00058 #else 00059 #include "commonucl/rtp.h" // UCL library 00060 #endif 00061 00062 class Frame; 00063 class PacketizationLayer; 00064 class SyncLayer; 00065 class TerminalCapabilities; 00066 class Statistics; 00067 00068 extern PortGenerator portGen; 00069 00070 /* how many secs worth of data should be prefetched on startup or if buffers dry out? 00071 * Type: SECONDS */ 00072 #ifdef LARGE_PREFETCH 00073 #define RTP_PREFETCH_SECS 20 00074 #else 00075 #define RTP_PREFETCH_SECS 8 00076 #endif 00077 00078 /* this is for gdb'd client or QuickTime to come up receiving! 00079 * Type: SECONDS */ 00080 #define RTP_SENDER_PRESLEEP 1 00081 00082 00083 /* General preQ Buffer Settings */ 00084 /* preQ is set to max 60 secs of fitting stream_BW of chosen video (eg. 60*500KBit/sec 00085 * Type: SECONDS */ 00086 #define RTP_CLIENT_PreQ_MAX_SECS 60 00087 00088 /* if client buffer has less than eg. 5 secs of video we force higher adaptation to fill buf 00089 * Type: SECONDS */ 00090 #define RTP_BUF_LOWWATER 5 00091 00092 /* if client buffer has more than eg. 30 secs of video we allow lower adaptation and drain buf 00093 * Type: SECONDS */ 00094 #define RTP_BUF_HIGHWATER 25 00095 00096 00108 class Rtp:public IO { 00109 public: 00110 00125 Rtp(const char *url, int remotePrt, const char *address, int localPrt, 00126 ESInfo * es, PacketizationLayer * packetization, bool writeOnly, 00127 const TerminalCapabilities *tc, GlobalTimer * globalTimer, Statistics *statistics,bool allowVopTimeDetection=true); 00128 virtual ~ Rtp(); 00129 00130 Statistics *getStatistics() { return stats; }; 00131 00132 void setESInfo(ESInfo * new_es); 00133 ESInfo* getESInfo() { return es;}; 00138 Frame *getFrame(); 00139 00144 int writeFrame(Frame * frm, ESInfo *out_es=NULL); 00145 00149 void resendHeader() { resendFrameHeader=true;} ; 00150 00151 00154 void run(); 00155 00160 bool open(); 00161 00162 State play(double prefetchTime); 00163 00164 State pause(); 00165 00166 State mute(); 00167 00168 bool close(bool immediate=false); 00169 00170 int getLocalPort() const { return localPort; }; 00171 00173 int getBufferFillLevelInPercent() const { return (int)(preQ.size/((float)preQ.max_size/100.0)); }; 00174 int getBufferFillLevel() const { return getBufferFillLevelInPercent(); }; 00175 00177 int getBufferFillLevelInBytes() const { return preQ.size; }; 00178 00180 int flushBuffer(long from_ts = 0, long to_ts = -1); 00181 00182 /* is this Rtp object for reading from network? (eg. client side) */ 00183 bool isInput() {return !writeToNetwork; }; 00184 /* is this Rtp object for writing to network? (eg. server side) */ 00185 bool isOutput() {return writeToNetwork; }; 00186 00188 bool destroy() { return true; } 00189 const char *getURL() const { return url; }; 00192 char *getSSRC(); 00193 00195 void setRtxInfo(const rtx_info* rtx); 00196 00197 const rtx_info* getRtxInfo() const { return rtx;}; 00198 00199 /* flushes the buffer before the given @param frameNumber 00200 * be aware that this currentFrameNumber will be reset if the input is changed with setESInfo() 00201 * and will be increased with every streamed out frame later on 00202 */ 00203 bool setToFrameNumber(u32 frameNumber); 00204 00205 /* flushes the buffer after the given @param frameNumber 00206 * be aware that this endFrameNumber will be reset if the input is changed with setESInfo() 00207 */ 00208 bool setEndFrameNumber(u32 frameNumber); 00209 00210 00211 /*******************************************************/ 00212 protected: 00213 00214 struct NetPacket_t; //fwd decl 00215 00216 static void RtpCallback(struct rtp *session, rtp_event * e); 00217 static void fb_print(struct rtp *session, uint32_t ssrc, rtcp_fb *fb); 00218 static void fb_handle(struct rtp *session, uint32_t ssrc, rtcp_fb *fb); 00219 static void rtp_data_handle(struct rtp *session, uint32_t ssrc, rtp_packet *packet); 00220 00221 typedef enum {Q_HEAD, Q_TAIL, Q_TS, Q_SEQ} QOrder; 00225 bool insertToPreQ(u8 *payload, long pl_size, Frame::FrameType type, long vop_size, int prio, 00226 u32 rtpTimestamp, u32 fragCounter, bool lastFrag, u32 rtp_seq, 00227 QOrder qo); 00228 00229 /* used to ignore preQ fill level and for pushback */ 00230 #define RTP_REINSERT true 00231 00234 bool reinsertToPreQ(NetPacket_t *p, uint rtp_seq); 00235 00240 bool addToPreQ(NetPacket_t *p, QOrder qo, bool pushback=false); 00241 00246 NetPacket_t *popPreQ(bool blocking=true); 00247 00248 00256 void calcAdaptPreQValues(int net_bw); 00257 00258 00264 void markFullFramePartially(bool dropped, bool sent, u32 ts); 00265 00275 void adaptPreQ(int net_bw); 00276 00280 int getNextPreQ_TS(); 00281 00282 // SendQ related methods 00283 bool pushNetPacket(NetPacket_t *p); 00284 NetPacket_t *popNetPacket(uint16_t rtp_seq); 00285 NetPacket_t *popNetPacketByRTXseq(uint16_t rtx_rtp_seq); 00286 00291 void sendQupdate(long streamout_sec); 00292 00297 void preQupdate(); 00298 00299 /* @param NetPacket_t takes a NetPacket and sends it either as new data or as RTX 00300 * ATTN: it sets the p->rtp_seq and, if applicable, p->rtx_rtp_seq and timestamps 00301 * @returns the number of sent bytes or -1 on error */ 00302 int doSend(NetPacket_t *p); 00303 00304 void sendThread(); 00305 void readThread(); 00306 00311 void ucl_update(u32 ts, u32 timeout); 00312 00313 00314 /************************************************ 00315 * Variables *************************************/ 00316 00317 typedef struct NetPacket_t { 00318 uint32_t rtp_seq; // rtp sequence number 00319 00320 uint16_t rtx_rtp_seq; // seqNo of this resent packet on the RTX channel 00321 int resent_counter; // how often was this pkt resent? 00322 bool acked; // already acked? 00323 00324 u32 rtp_ts; // rtp composition timestamp 00325 double sent_dtime; // time passed since thread_start_dtime 00326 double resent_dtime; 00327 00328 Frame::FrameType vop_type; // I,P,B, NN... this packet might be just a fragment! 00329 u32 vop_size; // NOT the actual packet size, but the full frame size! 00330 int prio; // adaptation priority 0..high (definitely keep) (eg. I,P) 00331 00332 bool partially_sent; // an arbitrary fragment of this TS is already on the net! 00333 bool partially_dropped; // an arbitrary fragment of this TS is already dropped! 00334 bool drop_me; // set if this packet was selected for adaptation 00335 00336 u32 frag_no; // 0..first packet, 1..n following fragments 00337 // on clientside: rtp_seq, which also gives a monotonic order 00338 // within TS! 00339 bool last_frag; // flag, if this is the last fragment of frame 00340 u8 *payload; 00341 u32 pl_size; // payload bytes 00342 NetPacket_t *next; 00343 } NetPacket_t; 00344 00345 struct CompareNetPackets 00346 { 00347 bool operator()(NetPacket_t*& np1, 00348 NetPacket_t*& np2) const 00349 { 00350 return (np1->prio < np2->prio); 00351 } 00352 }; 00353 00354 struct PreQ_t { 00355 NetPacket_t *Q; /* will be taken and sent. 00356 will then go into sendQ with the new rtp_seq */ 00357 NetPacket_t *Q_tail; /* points to the last elem */ 00358 00359 VMutex MUTEX_Q; 00360 VMutex MUTEX_Q_DATA_AVAIL; 00361 VMutex MUTEX_Q_FULL; 00362 VMutex MUTEX_Q_DONE; 00363 bool isDirty; 00364 bool needsPrefetching; 00365 00366 unsigned long max_size; 00367 unsigned long size; 00368 uint num_elems; 00369 uint num_full_frames; 00370 uint avg_bw; // avg BW/sec of frames in PreQ, not of whole video! 00371 00372 uint32_t highest_rtp_seq; 00373 uint32_t highest_ts; 00374 } preQ; 00375 00376 00377 #define RTP_SENDQ_PRIME 37 00378 struct SendQ_t { 00379 NetPacket_t *Q[RTP_SENDQ_PRIME]; 00380 long size; 00381 uint num_elems; 00382 uint avg_bw; // avg BW/sec of frames in SendQ, not of whole video! 00383 VMutex MUTEX_Q; 00384 } sendQ; 00385 00386 00387 Statistics *stats; 00388 struct rtp *session; 00389 uint32_t sender_ssrc; 00390 int remotePort; 00391 int localPort; 00392 char *remoteAddress; 00393 #ifndef WIN32 00394 static const int TTL = 16; 00395 static const int MAX_PAYLOAD_SIZE = 65000; 00396 static const int RTP_PAYLOAD_TYPE = 96; 00397 #endif 00398 bool writeToNetwork; 00399 bool firstFrame; 00400 00401 //global state used by getFrame 00402 struct { 00403 int numProcessedFrames; 00404 int seqno; 00405 int act_ts; 00406 } IOFrameStat; 00407 00408 GlobalTimer * globalTimer; 00409 PacketizationLayer *pLayer; 00410 ESInfo *es; 00411 char *url; 00412 rtx_info* rtx; 00413 bool feedbackEnabled; 00414 bool rtxEnabled; 00415 00416 int64_t last_rr_seq_no; 00417 int64_t last_rr_sum_pkts_lost; 00418 double last_rr_lost_fract; 00419 double last_rr_received; 00420 00421 int64_t first_rtp_seq; 00422 uint16_t last_rtp_seq; 00423 int ts_offset; //if the server doesnt start at TS=0, but later, fix the offset.... 00424 00425 int64_t first_rtx_rtp_seq; 00426 uint16_t last_rtx_rtp_seq; 00427 int interarrival_time; // msecs 00428 int net_bw_before_superdrain; // when super-draining is necessary, we keep the old (good) net_bw 00429 int real_bw; // stream_bw, adjusted by 1 second +- DRAIN/FILL fact 00430 00431 bool threadWasPaused; 00432 bool allowVopTimeDetection; 00433 }; 00434 00435 #endif