/********** This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. (See .) This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA **********/ // "liveMedia" // Copyright (c) 1996-2016 Live Networks, Inc. All rights reserved. // Theora Video RTP Sources // Implementation #include "TheoraVideoRTPSource.hh" ////////// TheoraBufferedPacket and TheoraBufferedPacketFactory ////////// class TheoraBufferedPacket: public BufferedPacket { public: TheoraBufferedPacket(); virtual ~TheoraBufferedPacket(); private: // redefined virtual functions virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize); }; class TheoraBufferedPacketFactory: public BufferedPacketFactory { private: // redefined virtual functions virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource); }; ///////// TheoraVideoRTPSource implementation //////// TheoraVideoRTPSource* TheoraVideoRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat) { return new TheoraVideoRTPSource(env, RTPgs, rtpPayloadFormat); } TheoraVideoRTPSource ::TheoraVideoRTPSource(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat) : MultiFramedRTPSource(env, RTPgs, rtpPayloadFormat, 90000, new TheoraBufferedPacketFactory), fCurPacketIdent(0) { } TheoraVideoRTPSource::~TheoraVideoRTPSource() { } Boolean TheoraVideoRTPSource ::processSpecialHeader(BufferedPacket* packet, unsigned& resultSpecialHeaderSize) { unsigned char* headerStart = packet->data(); unsigned packetSize = packet->dataSize(); resultSpecialHeaderSize = 4; if (packetSize < resultSpecialHeaderSize) return False; // packet was too small // The first 3 bytes of the header are the "Ident" field: fCurPacketIdent = (headerStart[0]<<16) | (headerStart[1]<<8) | headerStart[2]; // The 4th byte is F|TDT|numPkts. // Reject any packet with TDT == 3: if ((headerStart[3]&0x30) == 0x30) return False; u_int8_t F = headerStart[3]>>6; fCurrentPacketBeginsFrame = F <= 1; // "Not Fragmented" or "Start Fragment" fCurrentPacketCompletesFrame = F == 0 || F == 3; // "Not Fragmented" or "End Fragment" return True; } char const* TheoraVideoRTPSource::MIMEtype() const { return "video/THEORA"; } ////////// TheoraBufferedPacket and TheoraBufferedPacketFactory implementation ////////// TheoraBufferedPacket::TheoraBufferedPacket() { } TheoraBufferedPacket::~TheoraBufferedPacket() { } unsigned TheoraBufferedPacket ::nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize) { if (dataSize < 2) { // There's not enough space for a 2-byte header. TARFU! Just return the data that's left: return dataSize; } unsigned frameSize = (framePtr[0]<<8) | framePtr[1]; framePtr += 2; if (frameSize > dataSize - 2) return dataSize - 2; // inconsistent frame size => just return all the data that's left return frameSize; } BufferedPacket* TheoraBufferedPacketFactory ::createNewPacket(MultiFramedRTPSource* /*ourSource*/) { return new TheoraBufferedPacket(); }