liveMedia/JPEGVideoRTPSink.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2012 Live Networks, Inc.  All rights reserved.
00018 // RTP sink for JPEG video (RFC 2435)
00019 // Implementation
00020 
00021 #include "JPEGVideoRTPSink.hh"
00022 #include "JPEGVideoSource.hh"
00023 
00024 JPEGVideoRTPSink
00025 ::JPEGVideoRTPSink(UsageEnvironment& env, Groupsock* RTPgs)
00026   : VideoRTPSink(env, RTPgs, 26, 90000, "JPEG") {
00027 }
00028 
00029 JPEGVideoRTPSink::~JPEGVideoRTPSink() {
00030 }
00031 
00032 JPEGVideoRTPSink*
00033 JPEGVideoRTPSink::createNew(UsageEnvironment& env, Groupsock* RTPgs) {
00034   return new JPEGVideoRTPSink(env, RTPgs);
00035 }
00036 
00037 Boolean JPEGVideoRTPSink::sourceIsCompatibleWithUs(MediaSource& source) {
00038   return source.isJPEGVideoSource();
00039 }
00040 
00041 Boolean JPEGVideoRTPSink
00042 ::frameCanAppearAfterPacketStart(unsigned char const* /*frameStart*/,
00043                                  unsigned /*numBytesInFrame*/) const {
00044   // A packet can contain only one frame
00045   return False;
00046 }
00047 
00048 void JPEGVideoRTPSink
00049 ::doSpecialFrameHandling(unsigned fragmentationOffset,
00050                          unsigned char* /*frameStart*/,
00051                          unsigned /*numBytesInFrame*/,
00052                          struct timeval framePresentationTime,
00053                          unsigned numRemainingBytes) {
00054   // Our source is known to be a JPEGVideoSource
00055   JPEGVideoSource* source = (JPEGVideoSource*)fSource;
00056   if (source == NULL) return; // sanity check
00057 
00058   u_int8_t mainJPEGHeader[8]; // the special header
00059   u_int8_t const type = source->type();
00060 
00061   mainJPEGHeader[0] = 0; // Type-specific
00062   mainJPEGHeader[1] = fragmentationOffset >> 16;
00063   mainJPEGHeader[2] = fragmentationOffset >> 8;
00064   mainJPEGHeader[3] = fragmentationOffset;
00065   mainJPEGHeader[4] = type;
00066   mainJPEGHeader[5] = source->qFactor();
00067   mainJPEGHeader[6] = source->width();
00068   mainJPEGHeader[7] = source->height();
00069   setSpecialHeaderBytes(mainJPEGHeader, sizeof mainJPEGHeader);
00070 
00071   unsigned restartMarkerHeaderSize = 0; // by default
00072   if (type >= 64 && type <= 127) {
00073     // There is also a Restart Marker Header:
00074     restartMarkerHeaderSize = 4;
00075     u_int16_t const restartInterval = source->restartInterval(); // should be non-zero
00076 
00077     u_int8_t restartMarkerHeader[4];
00078     restartMarkerHeader[0] = restartInterval>>8;
00079     restartMarkerHeader[1] = restartInterval&0xFF;
00080     restartMarkerHeader[2] = restartMarkerHeader[3] = 0xFF; // F=L=1; Restart Count = 0x3FFF
00081 
00082     setSpecialHeaderBytes(restartMarkerHeader, restartMarkerHeaderSize,
00083                           sizeof mainJPEGHeader/* start position */);
00084   }
00085 
00086   if (fragmentationOffset == 0 && source->qFactor() >= 128) {
00087     // There is also a Quantization Header:
00088     u_int8_t precision;
00089     u_int16_t length;
00090     u_int8_t const* quantizationTables
00091       = source->quantizationTables(precision, length);
00092 
00093     unsigned const quantizationHeaderSize = 4 + length;
00094     u_int8_t* quantizationHeader = new u_int8_t[quantizationHeaderSize];
00095 
00096     quantizationHeader[0] = 0; // MBZ
00097     quantizationHeader[1] = precision;
00098     quantizationHeader[2] = length >> 8;
00099     quantizationHeader[3] = length&0xFF;
00100     if (quantizationTables != NULL) { // sanity check
00101       for (u_int16_t i = 0; i < length; ++i) {
00102         quantizationHeader[4+i] = quantizationTables[i];
00103       }
00104     }
00105 
00106     setSpecialHeaderBytes(quantizationHeader, quantizationHeaderSize,
00107                           sizeof mainJPEGHeader + restartMarkerHeaderSize/* start position */);
00108     delete[] quantizationHeader;
00109   }
00110 
00111   if (numRemainingBytes == 0) {
00112     // This packet contains the last (or only) fragment of the frame.
00113     // Set the RTP 'M' ('marker') bit:
00114     setMarkerBit();
00115   }
00116 
00117   // Also set the RTP timestamp:
00118   setTimestamp(framePresentationTime);
00119 }
00120 
00121 
00122 unsigned JPEGVideoRTPSink::specialHeaderSize() const {
00123   // Our source is known to be a JPEGVideoSource
00124   JPEGVideoSource* source = (JPEGVideoSource*)fSource;
00125   if (source == NULL) return 0; // sanity check
00126 
00127   unsigned headerSize = 8; // by default
00128 
00129   u_int8_t const type = source->type();
00130   if (type >= 64 && type <= 127) {
00131     // There is also a Restart Marker Header:
00132     headerSize += 4;
00133   }
00134 
00135   if (curFragmentationOffset() == 0 && source->qFactor() >= 128) {
00136     // There is also a Quantization Header:
00137     u_int8_t dummy;
00138     u_int16_t quantizationTablesSize;
00139     (void)(source->quantizationTables(dummy, quantizationTablesSize));
00140 
00141     headerSize += 4 + quantizationTablesSize;
00142   }
00143 
00144   return headerSize;
00145 }

Generated on Thu May 10 20:25:12 2012 for live by  doxygen 1.5.2