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 | |