| 1 | /********** |
| 2 | This library is free software; you can redistribute it and/or modify it under |
| 3 | the terms of the GNU Lesser General Public License as published by the |
| 4 | Free Software Foundation; either version 3 of the License, or (at your |
| 5 | option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.) |
| 6 | |
| 7 | This library is distributed in the hope that it will be useful, but WITHOUT |
| 8 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 9 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
| 10 | more details. |
| 11 | |
| 12 | You should have received a copy of the GNU Lesser General Public License |
| 13 | along with this library; if not, write to the Free Software Foundation, Inc., |
| 14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 15 | **********/ |
| 16 | // "liveMedia" |
| 17 | // Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved. |
| 18 | // A class for generating MPEG-2 Transport Stream from one or more input |
| 19 | // Elementary Stream data sources |
| 20 | // C++ header |
| 21 | |
| 22 | #ifndef _MPEG2_TRANSPORT_STREAM_MULTIPLEXOR_HH |
| 23 | #define _MPEG2_TRANSPORT_STREAM_MULTIPLEXOR_HH |
| 24 | |
| 25 | #ifndef _FRAMED_SOURCE_HH |
| 26 | #include "FramedSource.hh" |
| 27 | #endif |
| 28 | #ifndef _MPEG_1OR2_DEMUX_HH |
| 29 | #include "MPEG1or2Demux.hh" // for SCR |
| 30 | #endif |
| 31 | |
| 32 | #define PID_TABLE_SIZE 0x2000 // 2^13 |
| 33 | |
| 34 | class MPEG2TransportStreamMultiplexor: public FramedSource { |
| 35 | public: |
| 36 | typedef void (onEndOfSegmentFunc)(void* clientData, double segmentDuration); |
| 37 | void setTimedSegmentation(unsigned segmentationDuration, |
| 38 | onEndOfSegmentFunc* onEndOfSegmentFunc = NULL, |
| 39 | void* onEndOfSegmentClientData = NULL); |
| 40 | // Specifies that PAT and PMT packets should be output every "segmentationDuration" seconds. |
| 41 | // (If "segmentationDuration" is 0 (the default value), then PAT and PMT packets are output |
| 42 | // at a preset frequency.) |
| 43 | // The optional function "onEndOfSegmentFunc" is called after each segment is output. |
| 44 | double currentSegmentDuration() const { return fCurrentSegmentDuration; } |
| 45 | // Valid only if "setTimedSegmentation()" was previously called with "segmentationDuration" > 0 |
| 46 | |
| 47 | Boolean canDeliverNewFrameImmediately() const { return fInputBufferBytesUsed < fInputBufferSize; } |
| 48 | // Can be used by a downstream reader to test whether the next call to "doGetNextFrame()" |
| 49 | // will deliver data immediately). |
| 50 | |
| 51 | protected: |
| 52 | MPEG2TransportStreamMultiplexor(UsageEnvironment& env); |
| 53 | virtual ~MPEG2TransportStreamMultiplexor(); |
| 54 | |
| 55 | virtual void awaitNewBuffer(unsigned char* oldBuffer) = 0; |
| 56 | // implemented by subclasses |
| 57 | |
| 58 | void handleNewBuffer(unsigned char* buffer, unsigned bufferSize, |
| 59 | int mpegVersion, MPEG1or2Demux::SCR scr, int16_t PID = -1); |
| 60 | // called by "awaitNewBuffer()" |
| 61 | // Note: For MPEG-4 video, set "mpegVersion" to 4; for H.264 video, set "mpegVersion" to 5; |
| 62 | // for H.265 video, set "mpegVersion" to 6. |
| 63 | // For Opus audio, set "mpegVersion" to 3. |
| 64 | // The buffer is assumed to be a PES packet, with a proper PES header. |
| 65 | // If "PID" is not -1, then it (currently, only the low 8 bits) is used as the stream's PID, |
| 66 | // otherwise the "stream_id" in the PES header is reused to be the stream's PID. |
| 67 | |
| 68 | private: |
| 69 | // Redefined virtual functions: |
| 70 | virtual Boolean isMPEG2TransportStreamMultiplexor() const; |
| 71 | virtual void doGetNextFrame(); |
| 72 | |
| 73 | private: |
| 74 | void deliverDataToClient(u_int16_t pid, unsigned char* buffer, unsigned bufferSize, |
| 75 | unsigned& startPositionInBuffer); |
| 76 | |
| 77 | void deliverPATPacket(); |
| 78 | void deliverPMTPacket(Boolean hasChanged); |
| 79 | |
| 80 | void setProgramStreamMap(unsigned frameSize); |
| 81 | |
| 82 | protected: |
| 83 | Boolean fHaveVideoStreams; |
| 84 | |
| 85 | private: |
| 86 | unsigned fOutgoingPacketCounter; |
| 87 | unsigned fProgramMapVersion; |
| 88 | u_int8_t fPreviousInputProgramMapVersion, fCurrentInputProgramMapVersion; |
| 89 | // These two fields are used if we see "program_stream_map"s in the input. |
| 90 | struct { |
| 91 | unsigned counter; |
| 92 | u_int8_t streamType; // for use in Program Maps |
| 93 | } fPIDState[PID_TABLE_SIZE]; |
| 94 | u_int16_t fPCR_PID, fCurrentPID; // only the low 13 bits are used |
| 95 | MPEG1or2Demux::SCR fPCR; |
| 96 | unsigned char* fInputBuffer; |
| 97 | unsigned fInputBufferSize, fInputBufferBytesUsed; |
| 98 | Boolean fIsFirstAdaptationField; |
| 99 | unsigned fSegmentationDuration; |
| 100 | // if nonzero, this is the number of seconds between successive 'segments'. Each 'segment' |
| 101 | // begins with a PAT, followed by a PMT. |
| 102 | // if zero (the default value), then the frequency of PATs and PMTs depends on the constants |
| 103 | // PAT_PERIOD_IF_UNTIMED and PMT_PERIOD_IF_UNTIMED, defined in the .cpp file. |
| 104 | Boolean segmentationIsTimed() const { return fSegmentationDuration > 0; } |
| 105 | u_int8_t fSegmentationIndication; |
| 106 | // used only if fSegmentationDuration > 0: |
| 107 | // 1 if a segment has just ended and the next packet is to be a PAT |
| 108 | // 2 if a segment has just ended and the following PAT has been sent; a PMT is next |
| 109 | // 0 otherwise |
| 110 | double fCurrentSegmentDuration, fPreviousPTS; // used only if fSegmentationDuration > 0 |
| 111 | onEndOfSegmentFunc* fOnEndOfSegmentFunc; // used only if fSegmentationDuration > 0 |
| 112 | void* fOnEndOfSegmentClientData; // ditto |
| 113 | }; |
| 114 | |
| 115 | |
| 116 | // The CRC calculation function that Transport Streams use. We make this function public |
| 117 | // here in case it's useful elsewhere: |
| 118 | u_int32_t calculateCRC(u_int8_t const* data, unsigned dataLength, u_int32_t initialValue = 0xFFFFFFFF); |
| 119 | |
| 120 | #endif |
| 121 | |