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 | // H.265 Video RTP Sources |
19 | // Implementation |
20 | |
21 | #include "H265VideoRTPSource.hh" |
22 | |
23 | ////////// H265BufferedPacket and H265BufferedPacketFactory ////////// |
24 | |
25 | class H265BufferedPacket: public BufferedPacket { |
26 | public: |
27 | H265BufferedPacket(H265VideoRTPSource& ourSource); |
28 | virtual ~H265BufferedPacket(); |
29 | |
30 | private: // redefined virtual functions |
31 | virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr, |
32 | unsigned dataSize); |
33 | private: |
34 | H265VideoRTPSource& fOurSource; |
35 | }; |
36 | |
37 | class H265BufferedPacketFactory: public BufferedPacketFactory { |
38 | private: // redefined virtual functions |
39 | virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource); |
40 | }; |
41 | |
42 | |
43 | ///////// H265VideoRTPSource implementation //////// |
44 | |
45 | H265VideoRTPSource* |
46 | H265VideoRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs, |
47 | unsigned char rtpPayloadFormat, |
48 | Boolean expectDONFields, |
49 | unsigned rtpTimestampFrequency) { |
50 | return new H265VideoRTPSource(env, RTPgs, rtpPayloadFormat, |
51 | expectDONFields, rtpTimestampFrequency); |
52 | } |
53 | |
54 | H265VideoRTPSource |
55 | ::H265VideoRTPSource(UsageEnvironment& env, Groupsock* RTPgs, |
56 | unsigned char rtpPayloadFormat, |
57 | Boolean expectDONFields, |
58 | unsigned rtpTimestampFrequency) |
59 | : MultiFramedRTPSource(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency, |
60 | new H265BufferedPacketFactory), |
61 | fExpectDONFields(expectDONFields), |
62 | fPreviousNALUnitDON(0), fCurrentNALUnitAbsDon((u_int64_t)(~0)) { |
63 | } |
64 | |
65 | H265VideoRTPSource::~H265VideoRTPSource() { |
66 | } |
67 | |
68 | Boolean H265VideoRTPSource |
69 | ::(BufferedPacket* packet, |
70 | unsigned& ) { |
71 | unsigned char* = packet->data(); |
72 | unsigned packetSize = packet->dataSize(); |
73 | u_int16_t DONL = 0; |
74 | unsigned numBytesToSkip; |
75 | |
76 | // Check the Payload Header's 'nal_unit_type' for special aggregation or fragmentation packets: |
77 | if (packetSize < 2) return False; |
78 | fCurPacketNALUnitType = (headerStart[0]&0x7E)>>1; |
79 | switch (fCurPacketNALUnitType) { |
80 | case 48: { // Aggregation Packet (AP) |
81 | // We skip over the 2-byte Payload Header, and the DONL header (if any). |
82 | if (fExpectDONFields) { |
83 | if (packetSize < 4) return False; |
84 | DONL = (headerStart[2]<<8)|headerStart[3]; |
85 | numBytesToSkip = 4; |
86 | } else { |
87 | numBytesToSkip = 2; |
88 | } |
89 | break; |
90 | } |
91 | case 49: { // Fragmentation Unit (FU) |
92 | // This NALU begins with the 2-byte Payload Header, the 1-byte FU header, and (optionally) |
93 | // the 2-byte DONL header. |
94 | // If the start bit is set, we reconstruct the original NAL header at the end of these |
95 | // 3 (or 5) bytes, and skip over the first 1 (or 3) bytes. |
96 | if (packetSize < 3) return False; |
97 | u_int8_t startBit = headerStart[2]&0x80; // from the FU header |
98 | u_int8_t endBit = headerStart[2]&0x40; // from the FU header |
99 | if (startBit) { |
100 | fCurrentPacketBeginsFrame = True; |
101 | |
102 | u_int8_t nal_unit_type = headerStart[2]&0x3F; // the last 6 bits of the FU header |
103 | u_int8_t [2]; |
104 | newNALHeader[0] = (headerStart[0]&0x81)|(nal_unit_type<<1); |
105 | newNALHeader[1] = headerStart[1]; |
106 | |
107 | if (fExpectDONFields) { |
108 | if (packetSize < 5) return False; |
109 | DONL = (headerStart[3]<<8)|headerStart[4]; |
110 | headerStart[3] = newNALHeader[0]; |
111 | headerStart[4] = newNALHeader[1]; |
112 | numBytesToSkip = 3; |
113 | } else { |
114 | headerStart[1] = newNALHeader[0]; |
115 | headerStart[2] = newNALHeader[1]; |
116 | numBytesToSkip = 1; |
117 | } |
118 | } else { |
119 | // The start bit is not set, so we skip over all headers: |
120 | fCurrentPacketBeginsFrame = False; |
121 | if (fExpectDONFields) { |
122 | if (packetSize < 5) return False; |
123 | DONL = (headerStart[3]<<8)|headerStart[4]; |
124 | numBytesToSkip = 5; |
125 | } else { |
126 | numBytesToSkip = 3; |
127 | } |
128 | } |
129 | fCurrentPacketCompletesFrame = (endBit != 0); |
130 | break; |
131 | } |
132 | default: { |
133 | // This packet contains one complete NAL unit: |
134 | fCurrentPacketBeginsFrame = fCurrentPacketCompletesFrame = True; |
135 | numBytesToSkip = 0; |
136 | break; |
137 | } |
138 | } |
139 | |
140 | computeAbsDonFromDON(DONL); |
141 | resultSpecialHeaderSize = numBytesToSkip; |
142 | return True; |
143 | } |
144 | |
145 | char const* H265VideoRTPSource::MIMEtype() const { |
146 | return "video/H265" ; |
147 | } |
148 | |
149 | void H265VideoRTPSource::computeAbsDonFromDON(u_int16_t DON) { |
150 | if (!fExpectDONFields) { |
151 | // Without DON fields in the input stream, we just increment our "AbsDon" count each time: |
152 | ++fCurrentNALUnitAbsDon; |
153 | } else { |
154 | if (fCurrentNALUnitAbsDon == (u_int64_t)(~0)) { |
155 | // This is the very first NAL unit, so "AbsDon" is just "DON": |
156 | fCurrentNALUnitAbsDon = (u_int64_t)DON; |
157 | } else { |
158 | // Use the previous NAL unit's DON and the current DON to compute "AbsDon": |
159 | // AbsDon[n] = AbsDon[n-1] + (DON[n] - DON[n-1]) mod 2^16 |
160 | short signedDiff16 = (short)(DON - fPreviousNALUnitDON); |
161 | int64_t signedDiff64 = (int64_t)signedDiff16; |
162 | fCurrentNALUnitAbsDon += signedDiff64; |
163 | } |
164 | |
165 | fPreviousNALUnitDON = DON; // for next time |
166 | } |
167 | } |
168 | |
169 | |
170 | ////////// H265BufferedPacket and H265BufferedPacketFactory implementation ////////// |
171 | |
172 | H265BufferedPacket::H265BufferedPacket(H265VideoRTPSource& ourSource) |
173 | : fOurSource(ourSource) { |
174 | } |
175 | |
176 | H265BufferedPacket::~H265BufferedPacket() { |
177 | } |
178 | |
179 | unsigned H265BufferedPacket |
180 | ::nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize) { |
181 | unsigned resultNALUSize = 0; // if an error occurs |
182 | |
183 | switch (fOurSource.fCurPacketNALUnitType) { |
184 | case 48: { // Aggregation Packet (AP) |
185 | if (useCount() > 0) { |
186 | // We're other than the first NAL unit inside this Aggregation Packet. |
187 | // Update our 'decoding order number': |
188 | u_int16_t DONL = 0; |
189 | if (fOurSource.fExpectDONFields) { |
190 | // There's a 1-byte DOND field next: |
191 | if (dataSize < 1) break; |
192 | u_int8_t DOND = framePtr[0]; |
193 | DONL = fOurSource.fPreviousNALUnitDON + (u_int16_t)(DOND + 1); |
194 | ++framePtr; |
195 | --dataSize; |
196 | } |
197 | fOurSource.computeAbsDonFromDON(DONL); |
198 | } |
199 | |
200 | // The next 2 bytes are the NAL unit size: |
201 | if (dataSize < 2) break; |
202 | resultNALUSize = (framePtr[0]<<8)|framePtr[1]; |
203 | framePtr += 2; |
204 | break; |
205 | } |
206 | default: { |
207 | // Common case: We use the entire packet data: |
208 | return dataSize; |
209 | } |
210 | } |
211 | |
212 | return (resultNALUSize <= dataSize) ? resultNALUSize : dataSize; |
213 | } |
214 | |
215 | BufferedPacket* H265BufferedPacketFactory |
216 | ::createNewPacket(MultiFramedRTPSource* ourSource) { |
217 | return new H265BufferedPacket((H265VideoRTPSource&)(*ourSource)); |
218 | } |
219 | |