/src/vvenc/source/Lib/EncoderLib/SEIwrite.cpp
Line | Count | Source |
1 | | /* ----------------------------------------------------------------------------- |
2 | | The copyright in this software is being made available under the Clear BSD |
3 | | License, included below. No patent rights, trademark rights and/or |
4 | | other Intellectual Property Rights other than the copyrights concerning |
5 | | the Software are granted under this license. |
6 | | |
7 | | The Clear BSD License |
8 | | |
9 | | Copyright (c) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors. |
10 | | All rights reserved. |
11 | | |
12 | | Redistribution and use in source and binary forms, with or without modification, |
13 | | are permitted (subject to the limitations in the disclaimer below) provided that |
14 | | the following conditions are met: |
15 | | |
16 | | * Redistributions of source code must retain the above copyright notice, |
17 | | this list of conditions and the following disclaimer. |
18 | | |
19 | | * Redistributions in binary form must reproduce the above copyright |
20 | | notice, this list of conditions and the following disclaimer in the |
21 | | documentation and/or other materials provided with the distribution. |
22 | | |
23 | | * Neither the name of the copyright holder nor the names of its |
24 | | contributors may be used to endorse or promote products derived from this |
25 | | software without specific prior written permission. |
26 | | |
27 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY |
28 | | THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
29 | | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
30 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
31 | | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
32 | | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
33 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
34 | | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
35 | | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
36 | | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
37 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
38 | | POSSIBILITY OF SUCH DAMAGE. |
39 | | |
40 | | |
41 | | ------------------------------------------------------------------------------------------- */ |
42 | | |
43 | | |
44 | | #include "SEIwrite.h" |
45 | | #include "CommonLib/BitStream.h" |
46 | | #include "CommonLib/SEI.h" |
47 | | #include "CommonLib/Slice.h" |
48 | | #include "CommonLib/Picture.h" |
49 | | #include "CommonLib/dtrace_next.h" |
50 | | |
51 | | //! \ingroup EncoderLib |
52 | | //! \{ |
53 | | |
54 | | namespace vvenc { |
55 | | |
56 | | void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &hrd, const uint32_t temporalId) |
57 | 0 | { |
58 | 0 | const SEIBufferingPeriod *bp = NULL; |
59 | 0 | switch (sei.payloadType()) |
60 | 0 | { |
61 | 0 | case SEI::USER_DATA_UNREGISTERED: |
62 | 0 | xWriteSEIuserDataUnregistered(*static_cast<const SEIuserDataUnregistered*>(&sei)); |
63 | 0 | break; |
64 | 0 | case SEI::DECODING_UNIT_INFO: |
65 | 0 | bp = &hrd.bufferingPeriodSEI; |
66 | 0 | CHECK (bp == nullptr, "Buffering Period need to be initialized in HRD to allow writing of Decoding Unit Information SEI"); |
67 | 0 | xWriteSEIDecodingUnitInfo(*static_cast<const SEIDecodingUnitInfo*>(& sei), *bp, temporalId); |
68 | 0 | break; |
69 | 0 | case SEI::SCALABLE_NESTING: |
70 | 0 | xWriteSEIScalableNesting(bs, *static_cast<const SEIScalableNesting*>(&sei)); |
71 | 0 | break; |
72 | 0 | case SEI::DECODED_PICTURE_HASH: |
73 | 0 | xWriteSEIDecodedPictureHash(*static_cast<const SEIDecodedPictureHash*>(&sei)); |
74 | 0 | break; |
75 | 0 | case SEI::BUFFERING_PERIOD: |
76 | 0 | xWriteSEIBufferingPeriod(*static_cast<const SEIBufferingPeriod*>(&sei)); |
77 | 0 | hrd.bufferingPeriodSEI = *(static_cast<const SEIBufferingPeriod*>(&sei)); |
78 | 0 | break; |
79 | 0 | case SEI::PICTURE_TIMING: |
80 | 0 | { |
81 | 0 | bp = &hrd.bufferingPeriodSEI; |
82 | 0 | CHECK (bp == nullptr, "Buffering Period need to be initialized in HRD to allow writing of Picture Timing SEI"); |
83 | 0 | xWriteSEIPictureTiming(*static_cast<const SEIPictureTiming*>(&sei), *bp, temporalId); |
84 | 0 | } |
85 | 0 | break; |
86 | 0 | case SEI::FRAME_FIELD_INFO: |
87 | 0 | xWriteSEIFrameFieldInfo(*static_cast<const SEIFrameFieldInfo*>(&sei)); |
88 | 0 | break; |
89 | 0 | case SEI::DEPENDENT_RAP_INDICATION: |
90 | 0 | xWriteSEIDependentRAPIndication(*static_cast<const SEIDependentRAPIndication*>(&sei)); |
91 | 0 | break; |
92 | 0 | case SEI::FRAME_PACKING: |
93 | 0 | xWriteSEIFramePacking(*static_cast<const SEIFramePacking*>(&sei)); |
94 | 0 | break; |
95 | 0 | case SEI::PARAMETER_SETS_INCLUSION_INDICATION: |
96 | 0 | xWriteSEIParameterSetsInclusionIndication(*static_cast<const SEIParameterSetsInclusionIndication*>(&sei)); |
97 | 0 | break; |
98 | 0 | case SEI::MASTERING_DISPLAY_COLOUR_VOLUME: |
99 | 0 | xWriteSEIMasteringDisplayColourVolume(*static_cast<const SEIMasteringDisplayColourVolume*>(&sei)); |
100 | 0 | break; |
101 | 0 | case SEI::ALTERNATIVE_TRANSFER_CHARACTERISTICS: |
102 | 0 | xWriteSEIAlternativeTransferCharacteristics(*static_cast<const SEIAlternativeTransferCharacteristics*>(&sei)); |
103 | 0 | break; |
104 | 0 | case SEI::EQUIRECTANGULAR_PROJECTION: |
105 | 0 | xWriteSEIEquirectangularProjection(*static_cast<const SEIEquirectangularProjection*>(&sei)); |
106 | 0 | break; |
107 | 0 | case SEI::SPHERE_ROTATION: |
108 | 0 | xWriteSEISphereRotation(*static_cast<const SEISphereRotation*>(&sei)); |
109 | 0 | break; |
110 | 0 | case SEI::OMNI_VIEWPORT: |
111 | 0 | xWriteSEIOmniViewport(*static_cast<const SEIOmniViewport*>(&sei)); |
112 | 0 | break; |
113 | 0 | case SEI::REGION_WISE_PACKING: |
114 | 0 | xWriteSEIRegionWisePacking(*static_cast<const SEIRegionWisePacking*>(&sei)); |
115 | 0 | break; |
116 | 0 | case SEI::GENERALIZED_CUBEMAP_PROJECTION: |
117 | 0 | xWriteSEIGeneralizedCubemapProjection(*static_cast<const SEIGeneralizedCubemapProjection*>(&sei)); |
118 | 0 | break; |
119 | 0 | case SEI::USER_DATA_REGISTERED_ITU_T_T35: |
120 | 0 | xWriteSEIUserDataRegistered(*static_cast<const SEIUserDataRegistered*>(&sei)); |
121 | 0 | break; |
122 | 0 | case SEI::FILM_GRAIN_CHARACTERISTICS: |
123 | 0 | xWriteSeiFgc(*static_cast<const SeiFgc*>(&sei)); |
124 | 0 | break; |
125 | 0 | case SEI::CONTENT_LIGHT_LEVEL_INFO: |
126 | 0 | xWriteSEIContentLightLevelInfo(*static_cast<const SEIContentLightLevelInfo*>(&sei)); |
127 | 0 | break; |
128 | 0 | case SEI::AMBIENT_VIEWING_ENVIRONMENT: |
129 | 0 | xWriteSEIAmbientViewingEnvironment(*static_cast<const SEIAmbientViewingEnvironment*>(&sei)); |
130 | 0 | break; |
131 | 0 | case SEI::CONTENT_COLOUR_VOLUME: |
132 | 0 | xWriteSEIContentColourVolume(*static_cast<const SEIContentColourVolume*>(&sei)); |
133 | 0 | break; |
134 | 0 | case SEI::SUBPICTURE_LEVEL_INFO: |
135 | 0 | xWriteSEISubpictureLevelInfo(*static_cast<const SEISubpicureLevelInfo*>(&sei)); |
136 | 0 | break; |
137 | 0 | case SEI::SAMPLE_ASPECT_RATIO_INFO: |
138 | 0 | xWriteSEISampleAspectRatioInfo(*static_cast<const SEISampleAspectRatioInfo*>(&sei)); |
139 | 0 | break; |
140 | 0 | default: |
141 | 0 | THROW("Trying to write unhandled SEI message"); |
142 | 0 | break; |
143 | 0 | } |
144 | 0 | xWriteByteAlign(); |
145 | 0 | } |
146 | | |
147 | | /** |
148 | | * marshal all SEI messages in provided list into one bitstream bs |
149 | | */ |
150 | | void SEIWriter::writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList, HRD &hrd, bool isNested, const uint32_t temporalId) |
151 | 0 | { |
152 | | #if ENABLE_TRACING |
153 | | if (g_HLSTraceEnable) |
154 | | DTRACE( g_trace_ctx, D_HEADER, "=========== SEI message ===========\n" ); |
155 | | #endif |
156 | 0 | OutputBitstream bs_count; |
157 | |
|
158 | 0 | for (SEIMessages::const_iterator sei=seiList.begin(); sei!=seiList.end(); sei++) |
159 | 0 | { |
160 | | // calculate how large the payload data is |
161 | | // TODO: this would be far nicer if it used vectored buffers |
162 | 0 | bs_count.clear(); |
163 | 0 | setBitstream(&bs_count); |
164 | |
|
165 | | #if ENABLE_TRACING |
166 | | bool traceEnable = g_HLSTraceEnable; |
167 | | g_HLSTraceEnable = false; |
168 | | #endif |
169 | 0 | xWriteSEIpayloadData(bs_count, **sei, hrd, temporalId); |
170 | | #if ENABLE_TRACING |
171 | | g_HLSTraceEnable = traceEnable; |
172 | | #endif |
173 | 0 | uint32_t payload_data_num_bits = bs_count.getNumberOfWrittenBits(); |
174 | 0 | CHECK(0 != payload_data_num_bits % 8, "Invalid number of payload data bits"); |
175 | |
|
176 | 0 | setBitstream(&bs); |
177 | 0 | uint32_t payloadType = (*sei)->payloadType(); |
178 | 0 | for (; payloadType >= 0xff; payloadType -= 0xff) |
179 | 0 | { |
180 | 0 | WRITE_CODE(0xff, 8, "payload_type"); |
181 | 0 | } |
182 | 0 | WRITE_CODE(payloadType, 8, "payload_type"); |
183 | |
|
184 | 0 | uint32_t payloadSize = payload_data_num_bits/8; |
185 | 0 | for (; payloadSize >= 0xff; payloadSize -= 0xff) |
186 | 0 | { |
187 | 0 | WRITE_CODE(0xff, 8, "payload_size"); |
188 | 0 | } |
189 | 0 | WRITE_CODE(payloadSize, 8, "payload_size"); |
190 | | |
191 | | /* payloadData */ |
192 | | #if ENABLE_TRACING |
193 | | if (g_HLSTraceEnable) |
194 | | DTRACE( g_trace_ctx, D_HEADER, "=========== %s SEI message ===========\n", SEI::getSEIMessageString( (SEI::PayloadType)payloadType ) ); |
195 | | #endif |
196 | |
|
197 | 0 | xWriteSEIpayloadData(bs, **sei, hrd, temporalId); |
198 | 0 | } |
199 | 0 | if (!isNested) |
200 | 0 | { |
201 | 0 | xWriteRbspTrailingBits(); |
202 | 0 | } |
203 | 0 | } |
204 | | |
205 | | /** |
206 | | * marshal a user_data_unregistered SEI message sei, storing the marshalled |
207 | | * representation in bitstream bs. |
208 | | */ |
209 | | void SEIWriter::xWriteSEIuserDataUnregistered(const SEIuserDataUnregistered &sei) |
210 | 0 | { |
211 | 0 | for (uint32_t i = 0; i < ISO_IEC_11578_LEN; i++) |
212 | 0 | { |
213 | 0 | WRITE_CODE(sei.uuid_iso_iec_11578[i], 8 , "sei.uuid_iso_iec_11578[i]"); |
214 | 0 | } |
215 | |
|
216 | 0 | for (uint32_t i = 0; i < sei.userDataLength; i++) |
217 | 0 | { |
218 | 0 | WRITE_CODE(sei.userData[i], 8 , "user_data_payload_byte"); |
219 | 0 | } |
220 | 0 | } |
221 | | |
222 | | /** |
223 | | * marshal a decoded picture hash SEI message, storing the marshalled |
224 | | * representation in bitstream bs. |
225 | | */ |
226 | | void SEIWriter::xWriteSEIDecodedPictureHash(const SEIDecodedPictureHash& sei) |
227 | 0 | { |
228 | 0 | const char *traceString="\0"; |
229 | 0 | switch (sei.method) |
230 | 0 | { |
231 | 0 | case VVENC_HASHTYPE_MD5: traceString="picture_md5"; break; |
232 | 0 | case VVENC_HASHTYPE_CRC: traceString="picture_crc"; break; |
233 | 0 | case VVENC_HASHTYPE_CHECKSUM: traceString="picture_checksum"; break; |
234 | 0 | default: THROW("Unknown hash type"); break; |
235 | 0 | } |
236 | | |
237 | 0 | if (traceString != 0) //use of this variable is needed to avoid a compiler error with G++ 4.6.1 |
238 | 0 | { |
239 | 0 | WRITE_CODE(sei.method, 8, "dph_sei_hash_type"); |
240 | 0 | WRITE_CODE(sei.singleCompFlag, 1, "dph_sei_single_component_flag"); |
241 | 0 | WRITE_CODE(0, 7, "dph_sei_reserved_zero_7bits"); |
242 | 0 | for(uint32_t i=0; i<uint32_t(sei.pictureHash.hash.size()); i++) |
243 | 0 | { |
244 | 0 | WRITE_CODE(sei.pictureHash.hash[i], 8, traceString); |
245 | 0 | } |
246 | 0 | } |
247 | 0 | } |
248 | | |
249 | | |
250 | | void SEIWriter::xWriteSEIDecodingUnitInfo(const SEIDecodingUnitInfo& sei, const SEIBufferingPeriod& bp, const uint32_t temporalId) |
251 | 0 | { |
252 | 0 | WRITE_UVLC(sei.decodingUnitIdx, "decoding_unit_idx"); |
253 | 0 | if( !bp.decodingUnitCpbParamsInPicTimingSeiFlag ) |
254 | 0 | { |
255 | 0 | for (int i = temporalId; i <= bp.bpMaxSubLayers - 1; i++) |
256 | 0 | { |
257 | 0 | if (i < bp.bpMaxSubLayers - 1) |
258 | 0 | { |
259 | 0 | WRITE_FLAG(sei.duiSubLayerDelaysPresent[i], "dui_sub_layer_delays_present_flag[i]"); |
260 | 0 | } |
261 | 0 | if( sei.duiSubLayerDelaysPresent[i] ) |
262 | 0 | WRITE_CODE( sei.duSptCpbRemovalDelayIncrement[i], bp.duCpbRemovalDelayIncrementLength, "du_spt_cpb_removal_delay_increment[i]"); |
263 | 0 | } |
264 | 0 | } |
265 | 0 | if (bp.decodingUnitDpbDuParamsInPicTimingSeiFlag) |
266 | 0 | { |
267 | 0 | WRITE_FLAG(sei.dpbOutputDuDelayPresent, "dpb_output_du_delay_present_flag"); |
268 | 0 | } |
269 | 0 | if(sei.dpbOutputDuDelayPresent) |
270 | 0 | { |
271 | 0 | WRITE_CODE(sei.picSptDpbOutputDuDelay, bp.dpbOutputDelayDuLength, "pic_spt_dpb_output_du_delay"); |
272 | 0 | } |
273 | 0 | } |
274 | | |
275 | | void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei) |
276 | 0 | { |
277 | 0 | WRITE_FLAG( sei.bpNalCpbParamsPresent, "bp_nal_hrd_parameters_present_flag"); |
278 | 0 | WRITE_FLAG( sei.bpVclCpbParamsPresent, "bp_vcl_hrd_parameters_present_flag"); |
279 | 0 | CHECK(!sei.bpNalCpbParamsPresent && !sei.bpVclCpbParamsPresent, "bp_nal_hrd_parameters_present_flag and/or bp_vcl_hrd_parameters_present_flag must be true"); |
280 | 0 | CHECK (sei.initialCpbRemovalDelayLength < 1, "sei.initialCpbRemovalDelayLength must be > 0"); |
281 | 0 | WRITE_CODE( sei.initialCpbRemovalDelayLength - 1, 5, "initial_cpb_removal_delay_length_minus1" ); |
282 | 0 | CHECK (sei.cpbRemovalDelayLength < 1, "sei.cpbRemovalDelayLength must be > 0"); |
283 | 0 | WRITE_CODE( sei.cpbRemovalDelayLength - 1, 5, "cpb_removal_delay_length_minus1" ); |
284 | 0 | CHECK (sei.dpbOutputDelayLength < 1, "sei.dpbOutputDelayLength must be > 0"); |
285 | 0 | WRITE_CODE( sei.dpbOutputDelayLength - 1, 5, "dpb_output_delay_length_minus1" ); |
286 | 0 | WRITE_FLAG( sei.bpDecodingUnitHrdParamsPresent, "bp_decoding_unit_hrd_params_present_flag" ); |
287 | 0 | if( sei.bpDecodingUnitHrdParamsPresent ) |
288 | 0 | { |
289 | 0 | CHECK (sei.duCpbRemovalDelayIncrementLength < 1, "sei.duCpbRemovalDelayIncrementLength must be > 0"); |
290 | 0 | WRITE_CODE( sei.duCpbRemovalDelayIncrementLength - 1, 5, "du_cpb_removal_delay_increment_length_minus1" ); |
291 | 0 | CHECK (sei.dpbOutputDelayDuLength < 1, "sei.dpbOutputDelayDuLength must be > 0"); |
292 | 0 | WRITE_CODE( sei.dpbOutputDelayDuLength - 1, 5, "dpb_output_delay_du_length_minus1" ); |
293 | 0 | WRITE_FLAG( sei.decodingUnitCpbParamsInPicTimingSeiFlag, "decoding_unit_cpb_params_in_pic_timing_sei_flag" ); |
294 | 0 | WRITE_FLAG(sei.decodingUnitDpbDuParamsInPicTimingSeiFlag, "decoding_unit_dpb_du_params_in_pic_timing_sei_flag"); |
295 | 0 | } |
296 | | |
297 | 0 | WRITE_FLAG( sei.concatenationFlag, "concatenation_flag"); |
298 | 0 | WRITE_FLAG( sei.additionalConcatenationInfoPresent, "additional_concatenation_info_present_flag"); |
299 | 0 | if (sei.additionalConcatenationInfoPresent) |
300 | 0 | { |
301 | 0 | WRITE_CODE( sei.maxInitialRemovalDelayForConcatenation, sei.initialCpbRemovalDelayLength, "max_initial_removal_delay_for_concatenation" ); |
302 | 0 | } |
303 | |
|
304 | 0 | CHECK (sei.auCpbRemovalDelayDelta < 1, "sei.auCpbRemovalDelayDelta must be > 0"); |
305 | 0 | WRITE_CODE( sei.auCpbRemovalDelayDelta - 1, sei.cpbRemovalDelayLength, "au_cpb_removal_delay_delta_minus1" ); |
306 | |
|
307 | 0 | CHECK(sei.bpMaxSubLayers < 1, "bp_max_sub_layers_minus1 must be > 0"); |
308 | 0 | WRITE_CODE(sei.bpMaxSubLayers - 1, 3, "bp_max_sub_layers_minus1"); |
309 | 0 | if (sei.bpMaxSubLayers - 1 > 0) |
310 | 0 | { |
311 | 0 | WRITE_FLAG(sei.cpbRemovalDelayDeltasPresent, "cpb_removal_delay_deltas_present_flag"); |
312 | 0 | } |
313 | |
|
314 | 0 | if (sei.cpbRemovalDelayDeltasPresent) |
315 | 0 | { |
316 | 0 | CHECK (sei.numCpbRemovalDelayDeltas < 1, "m_numCpbRemovalDelayDeltas must be > 0"); |
317 | 0 | WRITE_UVLC( sei.numCpbRemovalDelayDeltas - 1, "num_cpb_removal_delay_deltas_minus1" ); |
318 | 0 | for( int i = 0; i < sei.numCpbRemovalDelayDeltas; i ++ ) |
319 | 0 | { |
320 | 0 | WRITE_CODE( sei.cpbRemovalDelayDelta[i], sei.cpbRemovalDelayLength, "cpb_removal_delay_delta[i]" ); |
321 | 0 | } |
322 | 0 | } |
323 | 0 | CHECK (sei.bpCpbCnt < 1, "sei.bpCpbCnt must be > 0"); |
324 | 0 | WRITE_UVLC( sei.bpCpbCnt - 1, "bp_cpb_cnt_minus1"); |
325 | 0 | if (sei.bpMaxSubLayers - 1 > 0) |
326 | 0 | { |
327 | 0 | WRITE_FLAG(sei.sublayerInitialCpbRemovalDelayPresent, "bp_sublayer_initial_cpb_removal_delay_present_flag"); |
328 | 0 | } |
329 | 0 | for (int i = (sei.sublayerInitialCpbRemovalDelayPresent ? 0 : sei.bpMaxSubLayers - 1); i < sei.bpMaxSubLayers; i++) |
330 | 0 | { |
331 | 0 | for( int nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) |
332 | 0 | { |
333 | 0 | if( ( ( nalOrVcl == 0 ) && ( sei.bpNalCpbParamsPresent ) ) || |
334 | 0 | ( ( nalOrVcl == 1 ) && ( sei.bpVclCpbParamsPresent ) ) ) |
335 | 0 | { |
336 | 0 | for( int j = 0; j < sei.bpCpbCnt; j ++ ) |
337 | 0 | { |
338 | 0 | WRITE_CODE( sei.initialCpbRemovalDelay[j][i][nalOrVcl], sei.initialCpbRemovalDelayLength, "initial_cpb_removal_delay[j][i][nalOrVcl]" ); |
339 | 0 | WRITE_CODE( sei.initialCpbRemovalOffset[j][i][nalOrVcl], sei.initialCpbRemovalDelayLength, "initial_cpb_removal_delay_offset[j][i][nalOrVcl]" ); |
340 | 0 | } |
341 | 0 | } |
342 | 0 | } |
343 | 0 | } |
344 | 0 | if (sei.bpMaxSubLayers-1 > 0) |
345 | 0 | { |
346 | 0 | WRITE_FLAG(sei.sublayerDpbOutputOffsetsPresent, "bp_sublayer_dpb_output_offsets_present_flag"); |
347 | 0 | } |
348 | |
|
349 | 0 | if(sei.sublayerDpbOutputOffsetsPresent) |
350 | 0 | { |
351 | 0 | for(int i = 0; i < sei.bpMaxSubLayers - 1; i++) |
352 | 0 | { |
353 | 0 | WRITE_UVLC( sei.dpbOutputTidOffset[i], "dpb_output_tid_offset[i]" ); |
354 | 0 | } |
355 | 0 | } |
356 | 0 | WRITE_FLAG(sei.altCpbParamsPresent, "bp_alt_cpb_params_present_flag"); |
357 | 0 | if (sei.altCpbParamsPresent) |
358 | 0 | { |
359 | 0 | WRITE_FLAG(sei.useAltCpbParamsFlag, "use_alt_cpb_params_flag"); |
360 | 0 | } |
361 | |
|
362 | 0 | } |
363 | | |
364 | | void SEIWriter::xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SEIBufferingPeriod &bp, const uint32_t temporalId) |
365 | 0 | { |
366 | 0 | WRITE_CODE( sei.auCpbRemovalDelay[bp.bpMaxSubLayers - 1] - 1, bp.cpbRemovalDelayLength, "pt_cpb_removal_delay_minus1[bp_max_sub_layers_minus1]" ); |
367 | 0 | for (int i = temporalId; i < bp.bpMaxSubLayers - 1; i++) |
368 | 0 | { |
369 | 0 | WRITE_FLAG(sei.ptSubLayerDelaysPresent[i], "pt_sub_layer_delays_present_flag[i]"); |
370 | 0 | if (sei.ptSubLayerDelaysPresent[i]) |
371 | 0 | { |
372 | 0 | if (bp.cpbRemovalDelayDeltasPresent) |
373 | 0 | { |
374 | 0 | WRITE_FLAG(sei.cpbRemovalDelayDeltaEnabledFlag[i], "pt_cpb_removal_delay_delta_enabled_flag[i]"); |
375 | 0 | } |
376 | 0 | if (sei.cpbRemovalDelayDeltaEnabledFlag[i]) |
377 | 0 | { |
378 | 0 | if ((bp.numCpbRemovalDelayDeltas - 1) > 0) |
379 | 0 | { |
380 | 0 | WRITE_CODE(sei.cpbRemovalDelayDeltaIdx[i], ceilLog2(bp.numCpbRemovalDelayDeltas), "pt_cpb_removal_delay_delta_idx[i]"); |
381 | 0 | } |
382 | 0 | } |
383 | 0 | else |
384 | 0 | { |
385 | 0 | WRITE_CODE(sei.auCpbRemovalDelay[i] - 1, bp.cpbRemovalDelayLength, "pt_cpb_removal_delay_minus1[i]"); |
386 | 0 | } |
387 | 0 | } |
388 | 0 | } |
389 | 0 | WRITE_CODE(sei.picDpbOutputDelay, bp.dpbOutputDelayLength, "pt_dpb_output_delay"); |
390 | 0 | if( bp.altCpbParamsPresent ) |
391 | 0 | { |
392 | 0 | WRITE_FLAG( sei.cpbAltTimingInfoPresent, "cpb_alt_timing_info_present_flag" ); |
393 | 0 | if( sei.cpbAltTimingInfoPresent ) |
394 | 0 | { |
395 | 0 | if (bp.bpNalCpbParamsPresent) |
396 | 0 | { |
397 | 0 | for (int i = (bp.sublayerInitialCpbRemovalDelayPresent ? 0 : bp.bpMaxSubLayers - 1); i <= bp.bpMaxSubLayers - 1; ++i) |
398 | 0 | { |
399 | 0 | for (int j = 0; j < bp.bpCpbCnt; j++) |
400 | 0 | { |
401 | 0 | WRITE_CODE(sei.nalCpbAltInitialRemovalDelayDelta[i][j], bp.initialCpbRemovalDelayLength, |
402 | 0 | "nal_cpb_alt_initial_cpb_removal_delay_delta[ i ][ j ]"); |
403 | 0 | WRITE_CODE(sei.nalCpbAltInitialRemovalOffsetDelta[i][j], bp.initialCpbRemovalDelayLength, |
404 | 0 | "nal_cpb_alt_initial_cpb_removal_offset_delta[ i ][ j ]"); |
405 | 0 | } |
406 | 0 | WRITE_CODE(sei.nalCpbDelayOffset[i], bp.cpbRemovalDelayLength, "nal_cpb_delay_offset[ i ]"); |
407 | 0 | WRITE_CODE(sei.nalDpbDelayOffset[i], bp.dpbOutputDelayLength, "nal_dpb_delay_offset[ i ]"); |
408 | 0 | } |
409 | 0 | } |
410 | |
|
411 | 0 | if (bp.bpVclCpbParamsPresent) |
412 | 0 | { |
413 | 0 | for (int i = (bp.sublayerInitialCpbRemovalDelayPresent ? 0 : bp.bpMaxSubLayers - 1); i <= bp.bpMaxSubLayers - 1; ++i) |
414 | 0 | { |
415 | 0 | for (int j = 0; j < bp.bpCpbCnt; j++) |
416 | 0 | { |
417 | 0 | WRITE_CODE(sei.vclCpbAltInitialRemovalDelayDelta[i][j], bp.initialCpbRemovalDelayLength, |
418 | 0 | "vcl_cpb_alt_initial_cpb_removal_delay_delta[ i ][ j ]"); |
419 | 0 | WRITE_CODE(sei.vclCpbAltInitialRemovalOffsetDelta[i][j], bp.initialCpbRemovalDelayLength, |
420 | 0 | "vcl_cpb_alt_initial_cpb_removal_offset_delta[ i ][ j ]"); |
421 | 0 | } |
422 | 0 | WRITE_CODE(sei.vclCpbDelayOffset[i], bp.cpbRemovalDelayLength, "vcl_cpb_delay_offset[ i ]"); |
423 | 0 | WRITE_CODE(sei.vclDpbDelayOffset[i], bp.dpbOutputDelayLength, "vcl_dpb_delay_offset[ i ]"); |
424 | 0 | } |
425 | 0 | } |
426 | 0 | } |
427 | 0 | } |
428 | 0 | if (bp.bpDecodingUnitHrdParamsPresent && bp.decodingUnitDpbDuParamsInPicTimingSeiFlag) |
429 | 0 | { |
430 | 0 | WRITE_CODE( sei.picDpbOutputDuDelay, bp.dpbOutputDelayDuLength, "pic_dpb_output_du_delay" ); |
431 | 0 | } |
432 | 0 | if( bp.bpDecodingUnitHrdParamsPresent && bp.decodingUnitCpbParamsInPicTimingSeiFlag ) |
433 | 0 | { |
434 | 0 | WRITE_UVLC( sei.numDecodingUnitsMinus1, "num_decoding_units_minus1" ); |
435 | 0 | if (sei.numDecodingUnitsMinus1 > 0) |
436 | 0 | { |
437 | 0 | WRITE_FLAG( sei.duCommonCpbRemovalDelayFlag, "du_commmon_cpb_removal_delay_flag" ); |
438 | 0 | if( sei.duCommonCpbRemovalDelayFlag ) |
439 | 0 | { |
440 | 0 | for( int i = temporalId; i < bp.bpMaxSubLayers - 1; i ++ ) |
441 | 0 | { |
442 | 0 | if( sei.ptSubLayerDelaysPresent[i] ) |
443 | 0 | WRITE_CODE( sei.duCommonCpbRemovalDelayMinus1[i], bp.duCpbRemovalDelayIncrementLength, "du_common_cpb_removal_delay_increment_minus1[i]" ); |
444 | 0 | } |
445 | 0 | } |
446 | 0 | for( int i = 0; i <= sei.numDecodingUnitsMinus1; i ++ ) |
447 | 0 | { |
448 | 0 | WRITE_UVLC( sei.numNalusInDuMinus1[i], "num_nalus_in_du_minus1[i]" ); |
449 | 0 | if( !sei.duCommonCpbRemovalDelayFlag && i < sei.numDecodingUnitsMinus1 ) |
450 | 0 | { |
451 | 0 | for( int j = temporalId; j < bp.bpMaxSubLayers - 1; j ++ ) |
452 | 0 | { |
453 | 0 | if( sei.ptSubLayerDelaysPresent[j] ) |
454 | 0 | WRITE_CODE( sei.duCpbRemovalDelayMinus1[i * bp.bpMaxSubLayers + j], bp.duCpbRemovalDelayIncrementLength, "du_cpb_removal_delay_increment_minus1[i][j]" ); |
455 | 0 | } |
456 | 0 | } |
457 | 0 | } |
458 | 0 | } |
459 | 0 | } |
460 | |
|
461 | 0 | if (bp.additionalConcatenationInfoPresent) |
462 | 0 | { |
463 | 0 | WRITE_FLAG( sei.delayForConcatenationEnsureFlag, "pt_delay_for_concatenation_ensured_flag" ); |
464 | 0 | } |
465 | 0 | WRITE_CODE( sei.ptDisplayElementalPeriodsMinus1, 8, "pt_display_elemental_periods_minus1" ); |
466 | 0 | } |
467 | | |
468 | | void SEIWriter::xWriteSEIFrameFieldInfo(const SEIFrameFieldInfo& sei) |
469 | 0 | { |
470 | 0 | WRITE_FLAG( sei.fieldPicFlag ? 1 : 0, "ffi_field_pic_flag" ); |
471 | 0 | if (sei.fieldPicFlag) |
472 | 0 | { |
473 | 0 | WRITE_FLAG( sei.bottomFieldFlag ? 1 : 0, "ffi_bottom_field_flag" ); |
474 | 0 | WRITE_FLAG( sei.pairingIndicatedFlag ? 1 : 0, "ffi_pairing_indicated_flag" ); |
475 | 0 | if (sei.pairingIndicatedFlag) |
476 | 0 | { |
477 | 0 | WRITE_FLAG( sei.pairedWithNextFieldFlag ? 1 : 0, "ffi_paired_with_next_field_flag" ); |
478 | 0 | } |
479 | 0 | } |
480 | 0 | else |
481 | 0 | { |
482 | 0 | WRITE_FLAG( sei.displayFieldsFromFrameFlag ? 1 : 0, "ffi_display_fields_from_frame_flag" ); |
483 | 0 | if (sei.displayFieldsFromFrameFlag) |
484 | 0 | { |
485 | 0 | WRITE_FLAG( sei.topFieldFirstFlag ? 1 : 0, "ffi_display_fields_from_frame_flag" ); |
486 | 0 | } |
487 | 0 | WRITE_CODE( sei.displayElementalPeriodsMinus1, 8, "ffi_display_elemental_periods_minus1" ); |
488 | 0 | } |
489 | 0 | WRITE_CODE( sei.sourceScanType, 2, "ffi_source_scan_type" ); |
490 | 0 | WRITE_FLAG( sei.duplicateFlag ? 1 : 0, "ffi_duplicate_flag" ); |
491 | 0 | } |
492 | | |
493 | | void SEIWriter::xWriteSEIDependentRAPIndication(const SEIDependentRAPIndication& /*sei*/) |
494 | 0 | { |
495 | | // intentionally empty |
496 | 0 | } |
497 | | |
498 | | void SEIWriter::xWriteSEIScalableNesting(OutputBitstream& bs, const SEIScalableNesting& sei) |
499 | 0 | { |
500 | 0 | CHECK (sei.nestedSEIs.size()<1, "There must be at lease one SEI message nested in the scalable nesting SEI.") |
501 | | |
502 | 0 | WRITE_FLAG(sei.snOlsFlag, "sn_ols_flag"); |
503 | 0 | WRITE_FLAG(sei.snSubpicFlag, "sn_subpic_flag"); |
504 | 0 | if (sei.snOlsFlag) |
505 | 0 | { |
506 | 0 | WRITE_UVLC(sei.snNumOlssMinus1, "sn_num_olss_minus1"); |
507 | 0 | for (uint32_t i = 0; i <= sei.snNumOlssMinus1; i++) |
508 | 0 | { |
509 | 0 | WRITE_UVLC(sei.snOlsIdxDeltaMinus1[i], "sn_ols_idx_delta_minus1[i]"); |
510 | 0 | } |
511 | 0 | } |
512 | 0 | else |
513 | 0 | { |
514 | 0 | WRITE_FLAG(sei.snAllLayersFlag, "sn_all_layers_flag"); |
515 | 0 | if (!sei.snAllLayersFlag) |
516 | 0 | { |
517 | 0 | WRITE_UVLC(sei.snNumLayersMinus1, "sn_num_layers"); |
518 | 0 | for (uint32_t i = 1; i <= sei.snNumLayersMinus1; i++) |
519 | 0 | { |
520 | 0 | WRITE_CODE(sei.snLayerId[i], 6, "sn_layer_id"); |
521 | 0 | } |
522 | 0 | } |
523 | 0 | } |
524 | 0 | if (sei.snSubpicFlag) |
525 | 0 | { |
526 | 0 | WRITE_UVLC( sei.snNumSubpics - 1, "sn_num_subpics_minus1"); |
527 | 0 | CHECK(sei.snSubpicIdLen < 1, "sn_subpic_id_len_minus1 must be >= 0"); |
528 | 0 | WRITE_UVLC( sei.snSubpicIdLen - 1, "sn_subpic_id_len_minus1"); |
529 | 0 | for (uint32_t i = 0; i < sei.snNumSubpics; i++) |
530 | 0 | { |
531 | 0 | WRITE_CODE(sei.snSubpicId[i], sei.snSubpicIdLen, "sn_subpic_id[i]"); |
532 | 0 | } |
533 | 0 | } |
534 | | |
535 | 0 | WRITE_UVLC( (uint32_t)sei.nestedSEIs.size() - 1, "sn_num_seis_minus1"); |
536 | | |
537 | | // byte alignment |
538 | 0 | while (m_pcBitIf->getNumberOfWrittenBits() % 8 != 0) |
539 | 0 | { |
540 | 0 | WRITE_FLAG(0, "sn_zero_bit"); |
541 | 0 | } |
542 | |
|
543 | 0 | SEIMessages bufferingPeriod = getSeisByType(sei.nestedSEIs, SEI::BUFFERING_PERIOD); |
544 | 0 | if (!bufferingPeriod.empty()) |
545 | 0 | { |
546 | 0 | SEIBufferingPeriod *bp = (SEIBufferingPeriod*)bufferingPeriod.front(); |
547 | 0 | m_nestingHrd.bufferingPeriodSEI = *(bp); |
548 | 0 | } |
549 | | |
550 | | // write nested SEI messages |
551 | 0 | writeSEImessages(bs, sei.nestedSEIs, m_nestingHrd, true, 0); |
552 | 0 | } |
553 | | |
554 | | void SEIWriter::xWriteSEIFramePacking(const SEIFramePacking& sei) |
555 | 0 | { |
556 | 0 | WRITE_UVLC( sei.arrangementId, "fp_arrangement_id" ); |
557 | 0 | WRITE_FLAG( sei.arrangementCancelFlag, "fp_arrangement_cancel_flag" ); |
558 | |
|
559 | 0 | if( sei.arrangementCancelFlag == 0 ) |
560 | 0 | { |
561 | 0 | WRITE_CODE( sei.arrangementType, 7, "fp_arrangement_type" ); |
562 | |
|
563 | 0 | WRITE_FLAG( sei.quincunxSamplingFlag, "fp_quincunx_sampling_flag" ); |
564 | 0 | WRITE_CODE( sei.contentInterpretationType, 6, "fp_content_interpretation_type" ); |
565 | 0 | WRITE_FLAG( sei.spatialFlippingFlag, "fp_spatial_flipping_flag" ); |
566 | 0 | WRITE_FLAG( sei.frame0FlippedFlag, "fp_frame0_flipped_flag" ); |
567 | 0 | WRITE_FLAG( sei.fieldViewsFlag, "fp_field_views_flag" ); |
568 | 0 | WRITE_FLAG( sei.currentFrameIsFrame0Flag, "fp_current_frame_is_frame0_flag" ); |
569 | |
|
570 | 0 | WRITE_FLAG( sei.frame0SelfContainedFlag, "fp_frame0_self_contained_flag" ); |
571 | 0 | WRITE_FLAG( sei.frame1SelfContainedFlag, "fp_frame1_self_contained_flag" ); |
572 | |
|
573 | 0 | if(sei.quincunxSamplingFlag == 0 && sei.arrangementType != 5) |
574 | 0 | { |
575 | 0 | WRITE_CODE( sei.frame0GridPositionX, 4, "fp_frame0_grid_position_x" ); |
576 | 0 | WRITE_CODE( sei.frame0GridPositionY, 4, "fp_frame0_grid_position_y" ); |
577 | 0 | WRITE_CODE( sei.frame1GridPositionX, 4, "fp_frame1_grid_position_x" ); |
578 | 0 | WRITE_CODE( sei.frame1GridPositionY, 4, "fp_frame1_grid_position_y" ); |
579 | 0 | } |
580 | |
|
581 | 0 | WRITE_CODE( sei.arrangementReservedByte, 8, "fp_frame_packing_arrangement_reserved_byte" ); |
582 | 0 | WRITE_FLAG( sei.arrangementPersistenceFlag, "fp_frame_packing_arrangement_persistence_flag" ); |
583 | 0 | } |
584 | |
|
585 | 0 | WRITE_FLAG( sei.upsampledAspectRatio, "fp_upsampled_aspect_ratio" ); |
586 | 0 | } |
587 | | |
588 | | |
589 | | void SEIWriter::xWriteSEIParameterSetsInclusionIndication(const SEIParameterSetsInclusionIndication& sei) |
590 | 0 | { |
591 | 0 | WRITE_FLAG(sei.selfContainedClvsFlag, "psii_self_contained_clvs_flag"); |
592 | 0 | } |
593 | | |
594 | | void SEIWriter::xWriteSEIMasteringDisplayColourVolume(const SEIMasteringDisplayColourVolume& sei) |
595 | 0 | { |
596 | 0 | WRITE_CODE( sei.values.primaries[0][0], 16, "mdcv_display_primaries_x[0]" ); |
597 | 0 | WRITE_CODE( sei.values.primaries[0][1], 16, "mdcv_display_primaries_y[0]" ); |
598 | |
|
599 | 0 | WRITE_CODE( sei.values.primaries[1][0], 16, "mdcv_display_primaries_x[1]" ); |
600 | 0 | WRITE_CODE( sei.values.primaries[1][1], 16, "mdcv_display_primaries_y[1]" ); |
601 | |
|
602 | 0 | WRITE_CODE( sei.values.primaries[2][0], 16, "mdcv_display_primaries_x[2]" ); |
603 | 0 | WRITE_CODE( sei.values.primaries[2][1], 16, "mdcv_display_primaries_y[2]" ); |
604 | |
|
605 | 0 | WRITE_CODE( sei.values.whitePoint[0], 16, "mdcv_white_point_x" ); |
606 | 0 | WRITE_CODE( sei.values.whitePoint[1], 16, "mdcv_white_point_y" ); |
607 | |
|
608 | 0 | WRITE_CODE( sei.values.maxLuminance, 32, "mdcv_max_display_mastering_luminance" ); |
609 | 0 | WRITE_CODE( sei.values.minLuminance, 32, "mdcv_min_display_mastering_luminance" ); |
610 | 0 | } |
611 | | |
612 | | void SEIWriter::xWriteByteAlign() |
613 | 0 | { |
614 | 0 | if( m_pcBitIf->getNumberOfWrittenBits() % 8 != 0) |
615 | 0 | { |
616 | 0 | WRITE_FLAG( 1, "payload_bit_equal_to_one" ); |
617 | 0 | while( m_pcBitIf->getNumberOfWrittenBits() % 8 != 0 ) |
618 | 0 | { |
619 | 0 | WRITE_FLAG( 0, "payload_bit_equal_to_zero" ); |
620 | 0 | } |
621 | 0 | } |
622 | 0 | } |
623 | | |
624 | | void SEIWriter::xWriteSEIAlternativeTransferCharacteristics(const SEIAlternativeTransferCharacteristics& sei) |
625 | 0 | { |
626 | 0 | WRITE_CODE(sei.preferredTransferCharacteristics, 8, "preferred_transfer_characteristics"); |
627 | 0 | } |
628 | | |
629 | | void SEIWriter::xWriteSEIEquirectangularProjection(const SEIEquirectangularProjection &sei) |
630 | 0 | { |
631 | 0 | WRITE_FLAG( sei.erpCancelFlag, "erp_cancel_flag" ); |
632 | 0 | if( !sei.erpCancelFlag ) |
633 | 0 | { |
634 | 0 | WRITE_FLAG( sei.erpPersistenceFlag, "erp_persistence_flag" ); |
635 | 0 | WRITE_FLAG( sei.erpGuardBandFlag, "erp_guard_band_flag" ); |
636 | 0 | WRITE_CODE( 0, 2, "erp_reserved_zero_2bits" ); |
637 | 0 | if ( sei.erpGuardBandFlag == 1) |
638 | 0 | { |
639 | 0 | WRITE_CODE( sei.erpGuardBandType, 3, "erp_guard_band_type" ); |
640 | 0 | WRITE_CODE( sei.erpLeftGuardBandWidth, 8, "erp_left_guard_band_width" ); |
641 | 0 | WRITE_CODE( sei.erpRightGuardBandWidth, 8, "erp_right_guard_band_width" ); |
642 | 0 | } |
643 | 0 | } |
644 | 0 | } |
645 | | |
646 | | void SEIWriter::xWriteSEISphereRotation(const SEISphereRotation &sei) |
647 | 0 | { |
648 | 0 | WRITE_FLAG( sei.sphereRotationCancelFlag, "sphere_rotation_cancel_flag" ); |
649 | 0 | if( !sei.sphereRotationCancelFlag ) |
650 | 0 | { |
651 | 0 | WRITE_FLAG( sei.sphereRotationPersistenceFlag, "sphere_rotation_persistence_flag" ); |
652 | 0 | WRITE_CODE( 0, 6, "sphere_rotation_reserved_zero_6bits" ); |
653 | 0 | WRITE_SCODE(sei.sphereRotationYaw, 32, "sphere_rotation_yaw" ); |
654 | 0 | WRITE_SCODE(sei.sphereRotationPitch, 32, "sphere_rotation_pitch" ); |
655 | 0 | WRITE_SCODE(sei.sphereRotationRoll, 32, "sphere_rotation_roll" ); |
656 | 0 | } |
657 | 0 | } |
658 | | |
659 | | void SEIWriter::xWriteSEIOmniViewport(const SEIOmniViewport &sei) |
660 | 0 | { |
661 | 0 | WRITE_CODE( sei.omniViewportId, 10, "omni_viewport_id" ); |
662 | 0 | WRITE_FLAG( sei.omniViewportCancelFlag, "omni_viewport_cancel_flag" ); |
663 | 0 | if ( !sei.omniViewportCancelFlag ) |
664 | 0 | { |
665 | 0 | WRITE_FLAG( sei.omniViewportPersistenceFlag, "omni_viewport_persistence_flag" ); |
666 | 0 | const uint32_t numRegions = (uint32_t) sei.omniViewportRegions.size(); |
667 | 0 | WRITE_CODE( numRegions - 1, 4, "omni_viewport_cnt_minus1" ); |
668 | 0 | for(uint32_t region=0; region<numRegions; region++) |
669 | 0 | { |
670 | 0 | const SEIOmniViewport::OmniViewport &viewport=sei.omniViewportRegions[region]; |
671 | 0 | WRITE_SCODE( viewport.azimuthCentre, 32, "omni_viewport_azimuth_centre" ); |
672 | 0 | WRITE_SCODE( viewport.elevationCentre, 32, "omni_viewport_elevation_centre" ); |
673 | 0 | WRITE_SCODE( viewport.tiltCentre, 32, "omni_viewport_tilt_center" ); |
674 | 0 | WRITE_CODE( viewport.horRange, 32, "omni_viewport_hor_range[i]" ); |
675 | 0 | WRITE_CODE( viewport.verRange, 32, "omni_viewport_ver_range[i]" ); |
676 | 0 | } |
677 | 0 | } |
678 | 0 | } |
679 | | |
680 | | void SEIWriter::xWriteSEIRegionWisePacking(const SEIRegionWisePacking &sei) |
681 | 0 | { |
682 | 0 | WRITE_FLAG( sei.rwpCancelFlag, "rwp_cancel_flag" ); |
683 | 0 | if(!sei.rwpCancelFlag) |
684 | 0 | { |
685 | 0 | WRITE_FLAG( sei.rwpPersistenceFlag, "rwp_persistence_flag" ); |
686 | 0 | WRITE_FLAG( sei.constituentPictureMatchingFlag, "rwp_constituent_picture_matching_flag" ); |
687 | 0 | WRITE_CODE( 0, 5, "rwp_reserved_zero_5bits" ); |
688 | 0 | WRITE_CODE( (uint32_t)sei.numPackedRegions, 8, "rwp_num_packed_regions" ); |
689 | 0 | WRITE_CODE( (uint32_t)sei.projPictureWidth, 32, "rwp_proj_picture_width" ); |
690 | 0 | WRITE_CODE( (uint32_t)sei.projPictureHeight, 32, "rwp_proj_picture_height" ); |
691 | 0 | WRITE_CODE( (uint32_t)sei.packedPictureWidth, 16, "rwp_packed_picture_width" ); |
692 | 0 | WRITE_CODE( (uint32_t)sei.packedPictureHeight, 16, "rwp_packed_picture_height" ); |
693 | 0 | for( int i=0; i < sei.numPackedRegions; i++ ) |
694 | 0 | { |
695 | 0 | WRITE_CODE( 0, 4, "rwp_reserved_zero_4bits" ); |
696 | 0 | WRITE_CODE( (uint32_t)sei.rwpTransformType[i], 3, "rwp_tTransform_type" ); |
697 | 0 | WRITE_FLAG( sei.rwpGuardBandFlag[i], "rwp_guard_band_flag" ); |
698 | 0 | WRITE_CODE( (uint32_t)sei.projRegionWidth[i], 32, "rwp_proj_region_width" ); |
699 | 0 | WRITE_CODE( (uint32_t)sei.projRegionHeight[i], 32, "rwp_proj_region_height" ); |
700 | 0 | WRITE_CODE( (uint32_t)sei.rwpProjRegionTop[i], 32, "rwp_proj_regionTop" ); |
701 | 0 | WRITE_CODE( (uint32_t)sei.projRegionLeft[i], 32, "rwp_proj_region_left" ); |
702 | 0 | WRITE_CODE( (uint32_t)sei.packedRegionWidth[i], 16, "rwp_packed_region_width" ); |
703 | 0 | WRITE_CODE( (uint32_t)sei.packedRegionHeight[i], 16, "rwp_packed_region_height" ); |
704 | 0 | WRITE_CODE( (uint32_t)sei.packedRegionTop[i], 16, "rwp_packed_region_top" ); |
705 | 0 | WRITE_CODE( (uint32_t)sei.packedRegionLeft[i], 16, "rwp_packed_region_left" ); |
706 | 0 | if( sei.rwpGuardBandFlag[i] ) |
707 | 0 | { |
708 | 0 | WRITE_CODE( (uint32_t)sei.rwpLeftGuardBandWidth[i], 8, "rwp_left_guard_band_width"); |
709 | 0 | WRITE_CODE( (uint32_t)sei.rwpRightGuardBandWidth[i], 8, "rwp_right_guard_band_width"); |
710 | 0 | WRITE_CODE( (uint32_t)sei.rwpTopGuardBandHeight[i], 8, "rwp_top_guard_band_height"); |
711 | 0 | WRITE_CODE( (uint32_t)sei.rwpBottomGuardBandHeight[i], 8, "rwp_bottom_guard_band_height"); |
712 | 0 | WRITE_FLAG( sei.rwpGuardBandNotUsedForPredFlag[i], "rwp_guard_band_not_used_forPred_flag" ); |
713 | 0 | for( int j=0; j < 4; j++ ) |
714 | 0 | { |
715 | 0 | WRITE_CODE( (uint32_t)sei.rwpGuardBandType[i*4 + j], 3, "rwp_guard_band_type"); |
716 | 0 | } |
717 | 0 | WRITE_CODE( 0, 3, "rwp_guard_band_reserved_zero_3bits" ); |
718 | 0 | } |
719 | 0 | } |
720 | 0 | } |
721 | 0 | } |
722 | | |
723 | | void SEIWriter::xWriteSEIGeneralizedCubemapProjection(const SEIGeneralizedCubemapProjection &sei) |
724 | 0 | { |
725 | 0 | WRITE_FLAG( sei.gcmpCancelFlag, "gcmp_cancel_flag" ); |
726 | 0 | if (!sei.gcmpCancelFlag) |
727 | 0 | { |
728 | 0 | WRITE_FLAG( sei.gcmpPersistenceFlag, "gcmp_persistence_flag" ); |
729 | 0 | WRITE_CODE( sei.gcmpPackingType, 3, "gcmp_packing_type" ); |
730 | 0 | WRITE_CODE( sei.gcmpMappingFunctionType, 2, "gcmp_mapping_function_type" ); |
731 | 0 | int numFace = sei.gcmpPackingType == 4 || sei.gcmpPackingType == 5 ? 5 : 6; |
732 | 0 | for (int i = 0; i < numFace; i++) |
733 | 0 | { |
734 | 0 | WRITE_CODE( sei.gcmpFaceIndex[i], 3, "gcmp_face_index" ); |
735 | 0 | WRITE_CODE( sei.gcmpFaceRotation[i], 2, "gcmp_face_rotation" ); |
736 | 0 | if (sei.gcmpMappingFunctionType == 2) |
737 | 0 | { |
738 | 0 | WRITE_CODE( sei.gcmpFunctionCoeffU[i], 7, "gcmp_function_coeff_u" ); |
739 | 0 | WRITE_FLAG( sei.gcmpFunctionUAffectedByVFlag[i], "gcmp_function_u_affected_by_v_flag" ); |
740 | 0 | WRITE_CODE( sei.gcmpFunctionCoeffV[i], 7, "gcmp_function_coeff_v" ); |
741 | 0 | WRITE_FLAG( sei.gcmpFunctionVAffectedByUFlag[i], "gcmp_function_v_affected_by_u_flag" ); |
742 | 0 | } |
743 | 0 | } |
744 | 0 | WRITE_FLAG( sei.gcmpGuardBandFlag, "gcmp_guard_band_flag" ); |
745 | 0 | if (sei.gcmpGuardBandFlag) |
746 | 0 | { |
747 | 0 | WRITE_CODE( sei.gcmpGuardBandType, 3, "gcmp_guard_band_type" ); |
748 | 0 | WRITE_FLAG( sei.gcmpGuardBandBoundaryExteriorFlag, "gcmp_guard_band_boundary_exterior_flag" ); |
749 | 0 | WRITE_CODE( sei.gcmpGuardBandSamplesMinus1, 4, "gcmp_guard_band_samples_minus1" ); |
750 | 0 | } |
751 | 0 | } |
752 | 0 | } |
753 | | |
754 | | void SEIWriter::xWriteSEISubpictureLevelInfo(const SEISubpicureLevelInfo &sei) |
755 | 0 | { |
756 | 0 | CHECK(sei.numRefLevels < 1, "SEISubpicureLevelInfo: numRefLevels must be greater than zero"); |
757 | 0 | CHECK(sei.numRefLevels != (int)sei.refLevelIdc.size(), "SEISubpicureLevelInfo: numRefLevels must be equal to the number of levels"); |
758 | 0 | if (sei.explicitFractionPresent) |
759 | 0 | { |
760 | 0 | CHECK(sei.numRefLevels != (int)sei.refLevelFraction.size(), "SEISubpicureLevelInfo: numRefLevels must be equal to the number of fractions"); |
761 | 0 | } |
762 | 0 | WRITE_CODE( (uint32_t)sei.numRefLevels - 1, 3, "sli_num_ref_levels_minus1"); |
763 | 0 | WRITE_FLAG( sei.cbrConstraintFlag, "sli_cbr_constraint_flag"); |
764 | 0 | WRITE_FLAG( sei.explicitFractionPresent, "sli_explicit_fraction_present_flag"); |
765 | 0 | if (sei.explicitFractionPresent) |
766 | 0 | { |
767 | 0 | WRITE_UVLC( sei.numSubpics -1 , "sli_num_subpics_minus1"); |
768 | 0 | WRITE_CODE( (uint32_t)sei.sliMaxSublayers - 1, 3, "sli_max_sublayers_minus1"); |
769 | 0 | WRITE_FLAG( sei.sliSublayerInfoPresent, "sli_sublayer_info_present_flag"); |
770 | 0 | while (!isByteAligned()) |
771 | 0 | { |
772 | 0 | WRITE_FLAG( 0, "sli_alignment_zero_bit"); |
773 | 0 | } |
774 | 0 | } |
775 | |
|
776 | 0 | for (int k = sei.sliSublayerInfoPresent ? 0 : sei.sliMaxSublayers - 1; k < sei.sliMaxSublayers; k++) |
777 | 0 | { |
778 | 0 | for (int i = 0; i < sei.numRefLevels; i++) |
779 | 0 | { |
780 | 0 | WRITE_CODE((uint32_t)sei.nonSubpicLayersFraction[i][k], 8, "sli_non_subpic_layers_fraction[i][k]"); |
781 | 0 | WRITE_CODE((uint32_t)sei.refLevelIdc[i][k], 8, "sli_ref_level_idc[i][k]"); |
782 | 0 | if (sei.explicitFractionPresent) |
783 | 0 | { |
784 | 0 | CHECK(sei.numSubpics != (int)sei.refLevelFraction[i].size(), "SEISubpicureLevelInfo: number of fractions differs from number of subpictures"); |
785 | 0 | for (int j = 0; j < sei.numSubpics; j++) |
786 | 0 | { |
787 | 0 | WRITE_CODE((uint32_t)sei.refLevelFraction[i][j][k], 8, "sli_ref_level_fraction_minus1[i][j][k]"); |
788 | 0 | } |
789 | 0 | } |
790 | 0 | } |
791 | 0 | } |
792 | 0 | } |
793 | | |
794 | | void SEIWriter::xWriteSEISampleAspectRatioInfo(const SEISampleAspectRatioInfo &sei) |
795 | 0 | { |
796 | 0 | WRITE_FLAG( sei.sariCancelFlag, "sari_cancel_flag" ); |
797 | 0 | if(!sei.sariCancelFlag) |
798 | 0 | { |
799 | 0 | WRITE_FLAG( sei.sariPersistenceFlag, "sari_persistence_flag" ); |
800 | 0 | WRITE_CODE( (uint32_t)sei.sariAspectRatioIdc, 8, "sari_aspect_ratio_idc"); |
801 | 0 | if (sei.sariAspectRatioIdc == 255) |
802 | 0 | { |
803 | 0 | WRITE_CODE( (uint32_t)sei.sariSarWidth, 16, "sari_sar_width"); |
804 | 0 | WRITE_CODE( (uint32_t)sei.sariSarHeight, 16, "sari_sar_height"); |
805 | 0 | } |
806 | 0 | } |
807 | 0 | } |
808 | | |
809 | | void SEIWriter::xWriteSEIUserDataRegistered(const SEIUserDataRegistered &sei) |
810 | 0 | { |
811 | 0 | WRITE_CODE((sei.ituCountryCode>255) ? 0xff : sei.ituCountryCode, 8, "itu_t_t35_country_code"); |
812 | 0 | if (sei.ituCountryCode >= 255) |
813 | 0 | { |
814 | 0 | assert(sei.ituCountryCode < 255 + 256); |
815 | 0 | WRITE_CODE(sei.ituCountryCode - 255, 8, "itu_t_t35_country_code_extension_byte"); |
816 | 0 | } |
817 | 0 | for (uint32_t i = 0; i<sei.userData.size(); i++) |
818 | 0 | { |
819 | 0 | WRITE_CODE(sei.userData[i], 8, "itu_t_t35_payload_byte"); |
820 | 0 | } |
821 | 0 | } |
822 | | |
823 | | void SEIWriter::xWriteSeiFgc(const SeiFgc &sei) |
824 | 0 | { |
825 | 0 | WRITE_FLAG(sei.fgcCancelFlag, "fg_characteristics_cancel_flag"); |
826 | 0 | if (!sei.fgcCancelFlag) |
827 | 0 | { |
828 | 0 | WRITE_CODE(sei.filmGrainModelId, 2, "fg_model_id"); |
829 | 0 | WRITE_FLAG(sei.separateColourDescriptionPresent, "fg_separate_colour_description_present_flag"); |
830 | 0 | if (sei.separateColourDescriptionPresent) |
831 | 0 | { |
832 | 0 | WRITE_CODE(sei.filmGrainBitDepthLumaMinus8, 3, "fg_bit_depth_luma_minus8"); |
833 | 0 | WRITE_CODE(sei.filmGrainBitDepthChromaMinus8, 3, "fg_bit_depth_chroma_minus8"); |
834 | 0 | WRITE_FLAG(sei.filmGrainFullRangeFlag, "fg_full_range_flag"); |
835 | 0 | WRITE_CODE(sei.filmGrainColourPrimaries, 8, "fg_colour_primaries"); |
836 | 0 | WRITE_CODE(sei.filmGrainTransferCharacteristics, 8, "fg_transfer_characteristics"); |
837 | 0 | WRITE_CODE(sei.filmGrainMatrixCoeffs, 8, "fg_matrix_coeffs"); |
838 | 0 | } |
839 | 0 | WRITE_CODE(sei.blendingModeId, 2, "fg_blending_mode_id"); |
840 | 0 | WRITE_CODE(sei.log2ScaleFactor, 4, "fg_log2_scale_factor"); |
841 | 0 | for (int c = 0; c<3; c++) |
842 | 0 | { |
843 | 0 | const SeiFgc::CompModel &cm = sei.compModel[c]; |
844 | 0 | const uint32_t numIntensityIntervals = static_cast<uint32_t>(cm.numIntensityIntervals); |
845 | 0 | const uint32_t numModelValues = cm.numModelValues; |
846 | 0 | WRITE_FLAG(sei.compModel[c].presentFlag && numIntensityIntervals>0 && numModelValues>0, "fg_comp_model_present_flag[c]"); |
847 | 0 | } |
848 | 0 | for (uint32_t c = 0; c<3; c++) |
849 | 0 | { |
850 | 0 | const SeiFgc::CompModel &cm = sei.compModel[c]; |
851 | 0 | const uint32_t numIntensityIntervals = static_cast<uint32_t>(cm.numIntensityIntervals); |
852 | 0 | const uint32_t numModelValues = cm.numModelValues; |
853 | 0 | if (cm.presentFlag && numIntensityIntervals>0 && numModelValues>0) |
854 | 0 | { |
855 | 0 | assert(numIntensityIntervals <= VVENC_MAX_NUM_INTENSITIES); |
856 | 0 | assert(numModelValues <= VVENC_MAX_NUM_INTENSITIES); |
857 | 0 | WRITE_CODE(numIntensityIntervals - 1, 8, "fg_num_intensity_intervals_minus1[c]"); |
858 | 0 | WRITE_CODE(numModelValues - 1, 3, "fg_num_model_values_minus1[c]"); |
859 | 0 | for (uint32_t interval = 0; interval<numIntensityIntervals; interval++) |
860 | 0 | { |
861 | 0 | const SeiFgc::CompModelIntensityValues &cmiv = cm.intensityValues[interval]; |
862 | 0 | WRITE_CODE(cmiv.intensityIntervalLowerBound, 8, "fg_intensity_interval_lower_bound[c][i]"); |
863 | 0 | WRITE_CODE(cmiv.intensityIntervalUpperBound, 8, "fg_intensity_interval_upper_bound[c][i]"); |
864 | 0 | assert(cmiv.compModelValue.size() == numModelValues); |
865 | 0 | for (uint32_t j = 0; j<cm.numModelValues; j++) |
866 | 0 | { |
867 | 0 | WRITE_SVLC(cmiv.compModelValue[j], "fg_comp_model_value[c][i]"); |
868 | 0 | } |
869 | 0 | } |
870 | 0 | } |
871 | 0 | } // for c |
872 | 0 | WRITE_FLAG(sei.fgcPersistenceFlag, "fg_characteristics_persistence_flag"); |
873 | 0 | } // cancel flag |
874 | 0 | } |
875 | | |
876 | | void SEIWriter::xWriteSEIContentLightLevelInfo(const SEIContentLightLevelInfo& sei) |
877 | 0 | { |
878 | 0 | WRITE_CODE( sei.maxContentLightLevel, 16, "clli_max_content_light_level" ); |
879 | 0 | WRITE_CODE( sei.maxPicAverageLightLevel, 16, "clli_max_pic_average_light_level" ); |
880 | 0 | } |
881 | | |
882 | | void SEIWriter::xWriteSEIAmbientViewingEnvironment(const SEIAmbientViewingEnvironment& sei) |
883 | 0 | { |
884 | 0 | WRITE_CODE(sei.ambientIlluminance, 32, "ambient_illuminance" ); |
885 | 0 | WRITE_CODE(sei.ambientLightX, 16, "ambient_light_x" ); |
886 | 0 | WRITE_CODE(sei.ambientLightY, 16, "ambient_light_y" ); |
887 | 0 | } |
888 | | |
889 | | void SEIWriter::xWriteSEIContentColourVolume(const SEIContentColourVolume &sei) |
890 | 0 | { |
891 | 0 | WRITE_FLAG(sei.ccvCancelFlag, "ccv_cancel_flag"); |
892 | 0 | if (!sei.ccvCancelFlag) |
893 | 0 | { |
894 | 0 | WRITE_FLAG(sei.ccvPersistenceFlag, "ccv_persistence_flag"); |
895 | 0 | WRITE_FLAG(sei.ccvPrimariesPresent, "ccv_primaries_present_flag"); |
896 | 0 | WRITE_FLAG(sei.ccvMinLuminanceValuePresent, "ccv_min_luminance_value_present_flag"); |
897 | 0 | WRITE_FLAG(sei.ccvMaxLuminanceValuePresent, "ccv_max_luminance_value_present_flag"); |
898 | 0 | WRITE_FLAG(sei.ccvAvgLuminanceValuePresent, "ccv_avg_luminance_value_present_flag"); |
899 | |
|
900 | 0 | if (sei.ccvPrimariesPresent == true) |
901 | 0 | { |
902 | 0 | for (int i = 0; i < MAX_NUM_COMP; i++) |
903 | 0 | { |
904 | 0 | WRITE_SCODE((int32_t)sei.ccvPrimariesX[i], 32, "ccv_primaries_x[i]"); |
905 | 0 | WRITE_SCODE((int32_t)sei.ccvPrimariesY[i], 32, "ccv_primaries_y[i]"); |
906 | 0 | } |
907 | 0 | } |
908 | |
|
909 | 0 | if (sei.ccvMinLuminanceValuePresent == true) |
910 | 0 | { |
911 | 0 | WRITE_CODE((uint32_t)sei.ccvMinLuminanceValue, 32, "ccv_min_luminance_value"); |
912 | 0 | } |
913 | 0 | if (sei.ccvMinLuminanceValuePresent == true) |
914 | 0 | { |
915 | 0 | WRITE_CODE((uint32_t)sei.ccvMaxLuminanceValue, 32, "ccv_max_luminance_value"); |
916 | 0 | } |
917 | 0 | if (sei.ccvMinLuminanceValuePresent == true) |
918 | 0 | { |
919 | 0 | WRITE_CODE((uint32_t)sei.ccvAvgLuminanceValue, 32, "ccv_avg_luminance_value"); |
920 | 0 | } |
921 | 0 | } |
922 | 0 | } |
923 | | |
924 | | } // namespace vvenc |
925 | | |
926 | | //! \} |
927 | | |