Hi Ross, Please would you consider adding this patch (or a variation thereof) into the source tree.
Currently there is no way to notify the application layer if a socket send error occurs. The patch addresses this by allowing the registration of a callback handler on the RTP sink. Uses: We use this functionality in our system to kick clients that have insufficient bandwidth to sustain the media session. Testing of the patch: - The patch has been tested over the period of about two months on an internal test system - We only considered the RTSP over TCP use case - During testing the client's TCP receiver buffer would typically fill first (after constraining the available network bandwidth), followed by the TCP send buffer filling on the server, followed by a send failure, at which point the callback handler is triggered that allows application developers to handle this if so desired. Patched against the current version of live555. (2011-09-19) with "diff -Naur". Best regards, Ralf
diff -Naur live-orig/liveMedia/include/MultiFramedRTPSink.hh live-new/liveMedia/include/MultiFramedRTPSink.hh --- live-orig/liveMedia/include/MultiFramedRTPSink.hh 2011-09-20 00:03:06.000000000 +0200 +++ live-new/liveMedia/include/MultiFramedRTPSink.hh 2011-10-04 13:54:49.632475345 +0200 @@ -30,6 +30,14 @@ public: void setPacketSizes(unsigned preferredPacketSize, unsigned maxPacketSize); + typedef void (onSendErrorFunc)(void* clientData); + void setOnSendErrorFunc(onSendErrorFunc* onSendErrorFunc, + void* onSendErrorFuncData) + { + fOnSendErrorFunc = onSendErrorFunc; + fOnSendErrorData = onSendErrorFuncData; + } + protected: MultiFramedRTPSink(UsageEnvironment& env, Groupsock* rtpgs, unsigned char rtpPayloadType, @@ -125,6 +133,9 @@ unsigned fCurFrameSpecificHeaderSize; // size in bytes of cur frame-specific header unsigned fTotalFrameSpecificHeaderSizes; // size of all frame-specific hdrs in pkt unsigned fOurMaxPacketSize; + + onSendErrorFunc* fOnSendErrorFunc; + void* fOnSendErrorData; }; #endif diff -Naur live-orig/liveMedia/include/RTPInterface.hh live-new/liveMedia/include/RTPInterface.hh --- live-orig/liveMedia/include/RTPInterface.hh 2011-09-20 00:03:06.000000000 +0200 +++ live-new/liveMedia/include/RTPInterface.hh 2011-10-04 13:54:39.344475346 +0200 @@ -64,7 +64,7 @@ void removeStreamSocket(int sockNum, unsigned char streamChannelId); void setServerRequestAlternativeByteHandler(int socketNum, ServerRequestAlternativeByteHandler* handler, void* clientData); - void sendPacket(unsigned char* packet, unsigned packetSize); + Boolean sendPacket(unsigned char* packet, unsigned packetSize); void startNetworkReading(TaskScheduler::BackgroundHandlerProc* handlerProc); Boolean handleRead(unsigned char* buffer, unsigned bufferMaxSize, diff -Naur live-orig/liveMedia/MultiFramedRTPSink.cpp live-new/liveMedia/MultiFramedRTPSink.cpp --- live-orig/liveMedia/MultiFramedRTPSink.cpp 2011-09-20 00:03:06.000000000 +0200 +++ live-new/liveMedia/MultiFramedRTPSink.cpp 2011-10-04 13:54:29.436475347 +0200 @@ -42,7 +42,8 @@ unsigned numChannels) : RTPSink(env, rtpGS, rtpPayloadType, rtpTimestampFrequency, rtpPayloadFormatName, numChannels), - fOutBuf(NULL), fCurFragmentationOffset(0), fPreviousFrameEndedFragmentation(False) { + fOutBuf(NULL), fCurFragmentationOffset(0), fPreviousFrameEndedFragmentation(False), + fOnSendErrorFunc(NULL), fOnSendErrorData(NULL){ setPacketSizes(1000, 1448); // Default max packet size (1500, minus allowance for IP, UDP, UMTP headers) // (Also, make it a multiple of 4 bytes, just in case that matters.) @@ -354,7 +355,15 @@ #ifdef TEST_LOSS if ((our_random()%10) != 0) // simulate 10% packet loss ##### #endif - fRTPInterface.sendPacket(fOutBuf->packet(), fOutBuf->curPacketSize()); + if (!fRTPInterface.sendPacket(fOutBuf->packet(), fOutBuf->curPacketSize())) + { + // if failure handler has been specified, call it + if (fOnSendErrorFunc != NULL) + { + (*fOnSendErrorFunc)(fOnSendErrorData); + } + } + ++fPacketCount; fTotalOctetCount += fOutBuf->curPacketSize(); fOctetCount += fOutBuf->curPacketSize() diff -Naur live-orig/liveMedia/RTPInterface.cpp live-new/liveMedia/RTPInterface.cpp --- live-orig/liveMedia/RTPInterface.cpp 2011-09-20 00:03:06.000000000 +0200 +++ live-new/liveMedia/RTPInterface.cpp 2011-10-04 13:54:17.260475348 +0200 @@ -29,7 +29,7 @@ // Helper routines and data structures, used to implement // sending/receiving RTP/RTCP over a TCP socket: -static void sendRTPOverTCP(unsigned char* packet, unsigned packetSize, +static Boolean sendRTPOverTCP(unsigned char* packet, unsigned packetSize, int socketNum, unsigned char streamChannelId); // Reading RTP-over-TCP is implemented using two levels of hash tables. @@ -182,16 +182,22 @@ } -void RTPInterface::sendPacket(unsigned char* packet, unsigned packetSize) { +Boolean RTPInterface::sendPacket(unsigned char* packet, unsigned packetSize) { + // This method will now return False if any of the sends fail + Boolean success = True; // Normal case: Send as a UDP packet: - fGS->output(envir(), fGS->ttl(), packet, packetSize); + if (!fGS->output(envir(), fGS->ttl(), packet, packetSize)) success = False; // Also, send over each of our TCP sockets: for (tcpStreamRecord* streams = fTCPStreams; streams != NULL; streams = streams->fNext) { - sendRTPOverTCP(packet, packetSize, - streams->fStreamSocketNum, streams->fStreamChannelId); + if (!sendRTPOverTCP(packet, packetSize, + streams->fStreamSocketNum, streams->fStreamChannelId)) + { + success = False; + } } + return success; } void RTPInterface @@ -267,7 +273,7 @@ ////////// Helper Functions - Implementation ///////// -void sendRTPOverTCP(unsigned char* packet, unsigned packetSize, +Boolean sendRTPOverTCP(unsigned char* packet, unsigned packetSize, int socketNum, unsigned char streamChannelId) { #ifdef DEBUG fprintf(stderr, "sendRTPOverTCP: %d bytes over channel %d (socket %d)\n", @@ -291,12 +297,13 @@ fprintf(stderr, "sendRTPOverTCP: completed\n"); fflush(stderr); #endif - return; + return True; } while (0); #ifdef DEBUG fprintf(stderr, "sendRTPOverTCP: failed!\n"); fflush(stderr); #endif + return False; } SocketDescriptor::SocketDescriptor(UsageEnvironment& env, int socketNum)
_______________________________________________ live-devel mailing list live-devel@lists.live555.com http://lists.live555.com/mailman/listinfo/live-devel