/** * @brief * * @param writeable * @param frame * * @return */ bool HttpImageStream::sendFrame( Select::CommsList &writeable, FramePtr frame ) { const ByteBuffer &packet = frame->buffer(); std::string txHeaders = "--imgboundary\r\n"; txHeaders += "Content-Type: image/jpeg\r\n"; txHeaders += stringtf( "Content-Length: %zd\r\n\r\n", packet.size() ); ByteBuffer txBuffer; txBuffer.reserve( packet.size()+128 ); txBuffer.append( txHeaders.c_str(), txHeaders.size() ); txBuffer.append( packet.data(), packet.size() ); txBuffer.append( "\r\n", 2 ); for ( Select::CommsList::iterator iter = writeable.begin(); iter != writeable.end(); iter++ ) { if ( TcpInetSocket *socket = dynamic_cast<TcpInetSocket *>(*iter) ) { if ( socket == mConnection->socket() ) { int nBytes = socket->write( txBuffer.data(), txBuffer.size() ); const FeedFrame *sourceFrame = frame->sourceFrame(); Debug( 4, "Wrote %d bytes on sd %d, frame %ju<-%ju", nBytes, socket->getWriteDesc(), frame->id(), sourceFrame->id() ); if ( nBytes != txBuffer.size() ) { Error( "Incomplete write, %d bytes instead of %zd", nBytes, packet.size() ); mStop = true; return( false ); } } } } return( true ); }
int RtpDataThread::run() { Debug( 2, "Starting data thread %d on port %d", mRtpSource.getSsrc(), mRtpSource.getLocalDataPort() ); SockAddrInet localAddr; UdpInetServer rtpDataSocket; if ( mRtpSource.getLocalHost() != "" ) { if ( !rtpDataSocket.bind( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort() ) ) Fatal( "Failed to bind RTP server" ); Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort() ); } else { if ( !rtpDataSocket.bind( mRtspThread.getAddressFamily() == AF_INET6 ? "::" : "0.0.0.0", mRtpSource.getLocalDataPort() ) ) Fatal( "Failed to bind RTP server" ); Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort() ); } Select select( 3 ); select.addReader( &rtpDataSocket ); unsigned char buffer[ZM_NETWORK_BUFSIZ]; while ( !mStop && select.wait() >= 0 ) { if ( mStop ) break; Select::CommsList readable = select.getReadable(); if ( readable.size() == 0 ) { Error( "RTP timed out" ); mStop = true; break; } for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ ) { if ( UdpInetServer *socket = dynamic_cast<UdpInetServer *>(*iter) ) { int nBytes = socket->recv( buffer, sizeof(buffer) ); Debug( 4, "Got %d bytes on sd %d", nBytes, socket->getReadDesc() ); if ( nBytes ) { recvPacket( buffer, nBytes ); } else { mStop = true; break; } } else { Panic( "Barfed" ); } } } rtpDataSocket.close(); mRtspThread.stop(); return( 0 ); }
/** * @brief * * @param writeable * @param frame * * @return */ bool HttpDataStream::sendFrame( Select::CommsList &writeable, FramePtr frame ) { const ByteBuffer &packet = frame->buffer(); for ( Select::CommsList::iterator iter = writeable.begin(); iter != writeable.end(); iter++ ) { if ( TcpInetSocket *socket = dynamic_cast<TcpInetSocket *>(*iter) ) { if ( socket == mConnection->socket() ) { int nBytes = socket->write( packet.data(), packet.size() ); const FeedFrame *sourceFrame = frame->sourceFrame(); Debug( 4, "Wrote %d bytes on sd %d, frame %ju<-%ju", nBytes, socket->getWriteDesc(), frame->id(), sourceFrame->id() ); if ( nBytes != packet.size() ) { Error( "Incomplete write, %d bytes instead of %zd", nBytes, packet.size() ); mStop = true; return( false ); } } } } return( true ); }
int RtpCtrlThread::run() { Debug( 2, "Starting control thread %lx on port %d", mRtpSource.getSsrc(), mRtpSource.getLocalCtrlPort() ); SockAddrInet localAddr, remoteAddr; bool sendReports; UdpInetSocket rtpCtrlServer; if ( mRtpSource.getLocalHost() != "" ) { localAddr.resolve( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort(), "udp" ); if ( !rtpCtrlServer.bind( localAddr ) ) Fatal( "Failed to bind RTCP server" ); sendReports = false; Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); } else { localAddr.resolve( mRtpSource.getLocalCtrlPort(), "udp" ); if ( !rtpCtrlServer.bind( localAddr ) ) Fatal( "Failed to bind RTCP server" ); Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); remoteAddr.resolve( mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort(), "udp" ); if ( !rtpCtrlServer.connect( remoteAddr ) ) Fatal( "Failed to connect RTCP server" ); Debug( 3, "Connected to %s:%d", mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort() ); sendReports = true; } Select select( 10 ); select.addReader( &rtpCtrlServer ); unsigned char buffer[BUFSIZ]; while ( !mStop && select.wait() >= 0 ) { if ( mStop ) break; Select::CommsList readable = select.getReadable(); if ( readable.size() == 0 ) { Error( "RTCP timed out" ); break; } for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ ) { if ( UdpInetSocket *socket = dynamic_cast<UdpInetSocket *>(*iter) ) { ssize_t nBytes = socket->recv( buffer, sizeof(buffer) ); Debug( 4, "Read %d bytes on sd %d", nBytes, socket->getReadDesc() ); if ( nBytes ) { recvPackets( buffer, nBytes ); if ( sendReports ) { unsigned char *bufferPtr = buffer; bufferPtr += generateRr( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); bufferPtr += generateSdes( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); Debug( 4, "Sending %d bytes on sd %d", bufferPtr-buffer, rtpCtrlServer.getWriteDesc() ); if ( (nBytes = rtpCtrlServer.send( buffer, bufferPtr-buffer )) < 0 ) Error( "Unable to send: %s", strerror( errno ) ); //Debug( 4, "Sent %d bytes on sd %d", nBytes, rtpCtrlServer.getWriteDesc() ); } } else { mStop = true; break; } } else { Fatal( "Barfed" ); } } } rtpCtrlServer.close(); mRtspThread.stop(); return( 0 ); }
int RtpCtrlThread::run() { Debug( 2, "Starting control thread %x on port %d", mRtpSource.getSsrc(), mRtpSource.getLocalCtrlPort() ); SockAddrInet localAddr, remoteAddr; bool sendReports; UdpInetSocket rtpCtrlServer; if ( mRtpSource.getLocalHost() != "" ) { if ( !rtpCtrlServer.bind( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ) ) Fatal( "Failed to bind RTCP server" ); sendReports = false; Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); } else { if ( !rtpCtrlServer.bind( mRtspThread.getAddressFamily() == AF_INET6 ? "::" : "0.0.0.0", mRtpSource.getLocalCtrlPort() ) ) Fatal( "Failed to bind RTCP server" ); Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); if ( !rtpCtrlServer.connect( mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort() ) ) Fatal( "Failed to connect RTCP server" ); Debug( 3, "Connected to %s:%d", mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort() ); sendReports = true; } // The only reason I can think of why we would have a timeout period is so that we can regularly send RR packets. // Why 10 seconds? If anything I think this should be whatever timeout value was given in the DESCRIBE response Select select( 10 ); select.addReader( &rtpCtrlServer ); unsigned char buffer[ZM_NETWORK_BUFSIZ]; time_t last_receive = time(NULL); bool timeout = false; // used as a flag that we had a timeout, and then sent an RR to see if we wake back up. Real timeout will happen when this is true. while ( !mStop && select.wait() >= 0 ) { time_t now = time(NULL); Select::CommsList readable = select.getReadable(); if ( readable.size() == 0 ) { if ( ! timeout ) { // With this code here, we will send an SDES and RR packet every 10 seconds ssize_t nBytes; unsigned char *bufferPtr = buffer; bufferPtr += generateRr( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); bufferPtr += generateSdes( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); Debug( 3, "Preventing timeout by sending %zd bytes on sd %d. Time since last receive: %d", bufferPtr-buffer, rtpCtrlServer.getWriteDesc(), ( now-last_receive) ); if ( (nBytes = rtpCtrlServer.send(buffer, bufferPtr-buffer)) < 0 ) Error("Unable to send: %s", strerror(errno)); timeout = true; continue; } else { //Error( "RTCP timed out" ); Debug(1, "RTCP timed out. Time since last receive: %d", ( now-last_receive) ); continue; //break; } } else { timeout = false; last_receive = time(NULL); } for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); ++iter ) { if ( UdpInetSocket *socket = dynamic_cast<UdpInetSocket *>(*iter) ) { ssize_t nBytes = socket->recv( buffer, sizeof(buffer) ); Debug( 4, "Read %zd bytes on sd %d", nBytes, socket->getReadDesc() ); if ( nBytes ) { recvPackets( buffer, nBytes ); if ( sendReports ) { unsigned char *bufferPtr = buffer; bufferPtr += generateRr( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); bufferPtr += generateSdes( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); Debug(3, "Sending %zd bytes on sd %d", bufferPtr-buffer, rtpCtrlServer.getWriteDesc()); if ( (nBytes = rtpCtrlServer.send( buffer, bufferPtr-buffer )) < 0 ) Error("Unable to send: %s", strerror(errno)); //Debug( 4, "Sent %d bytes on sd %d", nBytes, rtpCtrlServer.getWriteDesc() ); } } else { // Here is another case of not receiving some data causing us to terminate... why? Sometimes there are pauses in the interwebs. mStop = true; break; } } else { Panic("Barfed"); } // end if socket } // end foeach comms iterator } rtpCtrlServer.close(); mRtspThread.stop(); return 0; }