jrtplib 3.7.1
|
00001 /* 00002 00003 This file is a part of JRTPLIB 00004 Copyright (c) 1999-2007 Jori Liesenborgs 00005 00006 Contact: jori.liesenborgs@gmail.com 00007 00008 This library was developed at the "Expertisecentrum Digitale Media" 00009 (http://www.edm.uhasselt.be), a research center of the Hasselt University 00010 (http://www.uhasselt.be). The library is based upon work done for 00011 my thesis at the School for Knowledge Technology (Belgium/The Netherlands). 00012 00013 Permission is hereby granted, free of charge, to any person obtaining a 00014 copy of this software and associated documentation files (the "Software"), 00015 to deal in the Software without restriction, including without limitation 00016 the rights to use, copy, modify, merge, publish, distribute, sublicense, 00017 and/or sell copies of the Software, and to permit persons to whom the 00018 Software is furnished to do so, subject to the following conditions: 00019 00020 The above copyright notice and this permission notice shall be included 00021 in all copies or substantial portions of the Software. 00022 00023 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00024 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00025 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00026 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00027 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00028 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 00029 IN THE SOFTWARE. 00030 00031 */ 00032 00037 #ifndef RTCPCOMPOUNDPACKETBUILDER_H 00038 00039 #define RTCPCOMPOUNDPACKETBUILDER_H 00040 00041 #include "rtpconfig.h" 00042 #include "rtcpcompoundpacket.h" 00043 #include "rtptimeutilities.h" 00044 #include "rtcpsdespacket.h" 00045 #include "rtperrors.h" 00046 #include <list> 00047 00048 class RTPMemoryManager; 00049 00056 class RTCPCompoundPacketBuilder : public RTCPCompoundPacket 00057 { 00058 public: 00060 RTCPCompoundPacketBuilder(RTPMemoryManager *memmgr = 0); 00061 ~RTCPCompoundPacketBuilder(); 00062 00067 int InitBuild(size_t maxpacketsize); 00068 00073 int InitBuild(void *externalbuffer,size_t buffersize); 00074 00080 int StartSenderReport(uint32_t senderssrc,const RTPNTPTime &ntptimestamp,uint32_t rtptimestamp, 00081 uint32_t packetcount,uint32_t octetcount); 00082 00088 int StartReceiverReport(uint32_t senderssrc); 00089 00094 int AddReportBlock(uint32_t ssrc,uint8_t fractionlost,int32_t packetslost,uint32_t exthighestseq, 00095 uint32_t jitter,uint32_t lsr,uint32_t dlsr); 00096 00098 int AddSDESSource(uint32_t ssrc); 00099 00104 int AddSDESNormalItem(RTCPSDESPacket::ItemType t,const void *itemdata,uint8_t itemlength); 00105 #ifdef RTP_SUPPORT_SDESPRIV 00106 00107 int AddSDESPrivateItem(const void *prefixdata,uint8_t prefixlength,const void *valuedata, 00108 uint8_t valuelength); 00109 #endif // RTP_SUPPORT_SDESPRIV 00110 00116 int AddBYEPacket(uint32_t *ssrcs,uint8_t numssrcs,const void *reasondata,uint8_t reasonlength); 00117 00122 int AddAPPPacket(uint8_t subtype,uint32_t ssrc,const uint8_t name[4],const void *appdata,size_t appdatalen); 00123 00128 int EndBuild(); 00129 private: 00130 class Buffer 00131 { 00132 public: 00133 Buffer():packetdata(0),packetlength(0) { } 00134 Buffer(uint8_t *data,size_t len):packetdata(data),packetlength(len) { } 00135 00136 uint8_t *packetdata; 00137 size_t packetlength; 00138 }; 00139 00140 class Report : public RTPMemoryObject 00141 { 00142 public: 00143 Report(RTPMemoryManager *mgr) : RTPMemoryObject(mgr) 00144 { 00145 headerdata = (uint8_t *)headerdata32; 00146 isSR = false; 00147 headerlength = 0; 00148 } 00149 ~Report() { Clear(); } 00150 00151 void Clear() 00152 { 00153 std::list<Buffer>::const_iterator it; 00154 for (it = reportblocks.begin() ; it != reportblocks.end() ; it++) 00155 { 00156 if ((*it).packetdata) 00157 RTPDeleteByteArray((*it).packetdata,GetMemoryManager()); 00158 } 00159 reportblocks.clear(); 00160 isSR = false; 00161 headerlength = 0; 00162 } 00163 00164 size_t NeededBytes() 00165 { 00166 size_t x,n,d,r; 00167 n = reportblocks.size(); 00168 if (n == 0) 00169 { 00170 if (headerlength == 0) 00171 return 0; 00172 x = sizeof(RTCPCommonHeader)+headerlength; 00173 } 00174 else 00175 { 00176 x = n*sizeof(RTCPReceiverReport); 00177 d = n/31; // max 31 reportblocks per report 00178 r = n%31; 00179 if (r != 0) 00180 d++; 00181 x += d*(sizeof(RTCPCommonHeader)+sizeof(uint32_t)); /* header and SSRC */ 00182 if (isSR) 00183 x += sizeof(RTCPSenderReport); 00184 } 00185 return x; 00186 } 00187 00188 size_t NeededBytesWithExtraReportBlock() 00189 { 00190 size_t x,n,d,r; 00191 n = reportblocks.size() + 1; // +1 for the extra block 00192 x = n*sizeof(RTCPReceiverReport); 00193 d = n/31; // max 31 reportblocks per report 00194 r = n%31; 00195 if (r != 0) 00196 d++; 00197 x += d*(sizeof(RTCPCommonHeader)+sizeof(uint32_t)); /* header and SSRC */ 00198 if (isSR) 00199 x += sizeof(RTCPSenderReport); 00200 return x; 00201 } 00202 00203 bool isSR; 00204 00205 uint8_t *headerdata; 00206 uint32_t headerdata32[(sizeof(uint32_t)+sizeof(RTCPSenderReport))/sizeof(uint32_t)]; // either for ssrc and sender info or just ssrc 00207 size_t headerlength; 00208 std::list<Buffer> reportblocks; 00209 }; 00210 00211 class SDESSource : public RTPMemoryObject 00212 { 00213 public: 00214 SDESSource(uint32_t s,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),ssrc(s),totalitemsize(0) { } 00215 ~SDESSource() 00216 { 00217 std::list<Buffer>::const_iterator it; 00218 for (it = items.begin() ; it != items.end() ; it++) 00219 { 00220 if ((*it).packetdata) 00221 RTPDeleteByteArray((*it).packetdata,GetMemoryManager()); 00222 } 00223 items.clear(); 00224 } 00225 00226 size_t NeededBytes() 00227 { 00228 size_t x,r; 00229 x = totalitemsize + 1; // +1 for the 0 byte which terminates the item list 00230 r = x%sizeof(uint32_t); 00231 if (r != 0) 00232 x += (sizeof(uint32_t)-r); // make sure it ends on a 32 bit boundary 00233 x += sizeof(uint32_t); // for ssrc 00234 return x; 00235 } 00236 00237 size_t NeededBytesWithExtraItem(uint8_t itemdatalength) 00238 { 00239 size_t x,r; 00240 x = totalitemsize + sizeof(RTCPSDESHeader) + (size_t)itemdatalength + 1; 00241 r = x%sizeof(uint32_t); 00242 if (r != 0) 00243 x += (sizeof(uint32_t)-r); // make sure it ends on a 32 bit boundary 00244 x += sizeof(uint32_t); // for ssrc 00245 return x; 00246 } 00247 00248 void AddItem(uint8_t *buf,size_t len) 00249 { 00250 Buffer b(buf,len); 00251 totalitemsize += len; 00252 items.push_back(b); 00253 } 00254 00255 uint32_t ssrc; 00256 std::list<Buffer> items; 00257 private: 00258 size_t totalitemsize; 00259 }; 00260 00261 class SDES : public RTPMemoryObject 00262 { 00263 public: 00264 SDES(RTPMemoryManager *mgr) : RTPMemoryObject(mgr) { sdesit = sdessources.end(); } 00265 ~SDES() { Clear(); } 00266 00267 void Clear() 00268 { 00269 std::list<SDESSource *>::const_iterator it; 00270 00271 for (it = sdessources.begin() ; it != sdessources.end() ; it++) 00272 RTPDelete(*it,GetMemoryManager()); 00273 sdessources.clear(); 00274 } 00275 00276 int AddSSRC(uint32_t ssrc) 00277 { 00278 SDESSource *s = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_SDESSOURCE) SDESSource(ssrc,GetMemoryManager()); 00279 if (s == 0) 00280 return ERR_RTP_OUTOFMEM; 00281 sdessources.push_back(s); 00282 sdesit = sdessources.end(); 00283 sdesit--; 00284 return 0; 00285 } 00286 00287 int AddItem(uint8_t *buf,size_t len) 00288 { 00289 if (sdessources.empty()) 00290 return ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE; 00291 (*sdesit)->AddItem(buf,len); 00292 return 0; 00293 } 00294 00295 size_t NeededBytes() 00296 { 00297 std::list<SDESSource *>::const_iterator it; 00298 size_t x = 0; 00299 size_t n,d,r; 00300 00301 if (sdessources.empty()) 00302 return 0; 00303 00304 for (it = sdessources.begin() ; it != sdessources.end() ; it++) 00305 x += (*it)->NeededBytes(); 00306 n = sdessources.size(); 00307 d = n/31; 00308 r = n%31; 00309 if (r != 0) 00310 d++; 00311 x += d*sizeof(RTCPCommonHeader); 00312 return x; 00313 } 00314 00315 size_t NeededBytesWithExtraItem(uint8_t itemdatalength) 00316 { 00317 std::list<SDESSource *>::const_iterator it; 00318 size_t x = 0; 00319 size_t n,d,r; 00320 00321 if (sdessources.empty()) 00322 return 0; 00323 00324 for (it = sdessources.begin() ; it != sdesit ; it++) 00325 x += (*it)->NeededBytes(); 00326 x += (*sdesit)->NeededBytesWithExtraItem(itemdatalength); 00327 n = sdessources.size(); 00328 d = n/31; 00329 r = n%31; 00330 if (r != 0) 00331 d++; 00332 x += d*sizeof(RTCPCommonHeader); 00333 return x; 00334 } 00335 00336 size_t NeededBytesWithExtraSource() 00337 { 00338 std::list<SDESSource *>::const_iterator it; 00339 size_t x = 0; 00340 size_t n,d,r; 00341 00342 if (sdessources.empty()) 00343 return 0; 00344 00345 for (it = sdessources.begin() ; it != sdessources.end() ; it++) 00346 x += (*it)->NeededBytes(); 00347 00348 // for the extra source we'll need at least 8 bytes (ssrc and four 0 bytes) 00349 x += sizeof(uint32_t)*2; 00350 00351 n = sdessources.size() + 1; // also, the number of sources will increase 00352 d = n/31; 00353 r = n%31; 00354 if (r != 0) 00355 d++; 00356 x += d*sizeof(RTCPCommonHeader); 00357 return x; 00358 } 00359 00360 std::list<SDESSource *> sdessources; 00361 private: 00362 std::list<SDESSource *>::const_iterator sdesit; 00363 }; 00364 00365 size_t maximumpacketsize; 00366 uint8_t *buffer; 00367 bool external; 00368 bool arebuilding; 00369 00370 Report report; 00371 SDES sdes; 00372 00373 std::list<Buffer> byepackets; 00374 size_t byesize; 00375 00376 std::list<Buffer> apppackets; 00377 size_t appsize; 00378 00379 void ClearBuildBuffers(); 00380 }; 00381 00382 #endif // RTCPCOMPOUNDPACKETBUILDER_H 00383