Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/* The copyright in this software is being made available under the BSD
* License, included below. This software may be subject to other third party
* and contributor rights, including patent rights, and no such rights are
* granted under this license.
*
* Copyright (c) 2010-2020, ITU/ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <list>
#include <vector>
#include <stdio.h>
#include <fcntl.h>
#include "CommonLib/CommonDef.h"
#include "BitstreamExtractorApp.h"
#include "DecoderLib/AnnexBread.h"
#include "DecoderLib/NALread.h"
#include "EncoderLib/NALwrite.h"
#include "DecoderLib/VLCReader.h"
#include "EncoderLib/VLCWriter.h"
#include "EncoderLib/AnnexBwrite.h"
BitstreamExtractorApp::BitstreamExtractorApp()
#if JVET_P0118_OLS_EXTRACTION
:m_vpsId(-1)
#endif
{
}
void BitstreamExtractorApp::xPrintVPSInfo (VPS *vps)
{
msg (VERBOSE, "VPS Info: \n");
msg (VERBOSE, " VPS ID : %d\n", vps->getVPSId());
msg (VERBOSE, " Max layers : %d\n", vps->getMaxLayers());
msg (VERBOSE, " Max sub-layers : %d\n", vps->getMaxSubLayers());
msg (VERBOSE, " Number of OLS : %d\n", vps->getNumOutputLayerSets());
for (int olsIdx=0; olsIdx < vps->getNumOutputLayerSets(); olsIdx++)
{
vps->deriveTargetOutputLayerSet(olsIdx);
msg (VERBOSE, " OLS # %d\n", olsIdx);
msg (VERBOSE, " Output layers: ");
for( int i = 0; i < vps->m_targetOutputLayerIdSet.size(); i++ )
{
msg (VERBOSE, "%d ", vps->m_targetOutputLayerIdSet[i]);
}
msg (VERBOSE, "\n");
msg (VERBOSE, " Target layers: ");
for( int i = 0; i < vps->m_targetLayerIdSet.size(); i++ )
{
msg (VERBOSE, "%d ", vps->m_targetLayerIdSet[i]);
}
msg (VERBOSE, "\n");
}
}
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#if JVET_Q0397_SUB_PIC_EXTRACT
void BitstreamExtractorApp::xPrintSubPicInfo (PPS *pps)
{
msg (VERBOSE, "Subpic Info: \n");
msg (VERBOSE, " SPS ID : %d\n", pps->getSPSId());
msg (VERBOSE, " PPS ID : %d\n", pps->getPPSId());
msg (VERBOSE, " Subpic enabled : %s\n", pps->getNumSubPics() > 1 ? "yes": "no" );
if ( pps->getNumSubPics() > 1)
{
msg (VERBOSE, " Number of subpics : %d\n", pps->getNumSubPics() );
for (int i=0; i<pps->getNumSubPics(); i++)
{
SubPic subP = pps->getSubPic(i);
msg ( VERBOSE, " SubpicIdx #%d : TL=(%d, %d) Size CTU=(%d, %d) Size Pel=(%d, %d) SubpicID=%d\n", i, subP.getSubPicCtuTopLeftX(), subP.getSubPicCtuTopLeftY(),
subP.getSubPicWidthInCTUs(), subP.getSubPicHeightInCTUs(), subP.getSubPicWidthInLumaSample(), subP.getSubPicHeightInLumaSample(), subP.getSubPicID());
}
}
}
void BitstreamExtractorApp::xReadPicHeader(InputNALUnit &nalu)
{
m_hlSynaxReader.setBitstream(&nalu.getBitstream());
m_hlSynaxReader.parsePictureHeader(&m_picHeader, &m_parameterSetManager, true);
m_picHeader.setValid();
}
bool BitstreamExtractorApp::xCheckSliceSubpicture(InputNALUnit &nalu, int targetSubPicId)
{
m_hlSynaxReader.setBitstream(&nalu.getBitstream());
Slice slice;
slice.initSlice();
slice.setNalUnitType(nalu.m_nalUnitType);
slice.setNalUnitLayerId(nalu.m_nuhLayerId);
slice.setTLayer(nalu.m_temporalId);
m_hlSynaxReader.parseSliceHeader(&slice, &m_picHeader, &m_parameterSetManager, m_prevTid0Poc);
PPS *pps = m_parameterSetManager.getPPS(m_picHeader.getPPSId());
CHECK (nullptr==pps, "referenced PPS not found");
SPS *sps = m_parameterSetManager.getSPS(pps->getSPSId());
CHECK (nullptr==sps, "referenced SPS not found");
if (sps->getSubPicInfoPresentFlag())
{
// subpic ID is explicitly indicated
msg( VERBOSE, "found slice subpic id %d\n", slice.getSliceSubPicId());
return ( targetSubPicId == slice.getSliceSubPicId());
}
else
{
THROW ("Subpicture signalling disbled, cannot extract.");
}
return true;
}
void BitstreamExtractorApp::xRewriteSPS (SPS &targetSPS, const SPS &sourceSPS, SubPic &subPic)
{
targetSPS = sourceSPS;
// set the number of subpicture to 1, location should not be transmited
targetSPS.setNumSubPics(1);
// set the target subpicture ID as first ID
targetSPS.setSubPicIdMappingExplicitlySignalledFlag(true);
targetSPS.setSubPicIdMappingInSpsFlag(true);
targetSPS.setSubPicId(0, subPic.getSubPicID());
targetSPS.setMaxPicWidthInLumaSamples(subPic.getSubPicWidthInLumaSample());
targetSPS.setMaxPicHeightInLumaSamples(subPic.getSubPicHeightInLumaSample());
}
void BitstreamExtractorApp::xRewritePPS (PPS &targetPPS, const PPS &sourcePPS, SubPic &subPic)
{
targetPPS = sourcePPS;
// set number of subpictures to 1
targetPPS.setNumSubPics(1);
// set taget subpicture ID as first ID
targetPPS.setSubPicId(0, m_subPicId);
// we send the ID in the SPS, so don't sent it in the PPS (hard coded decision)
targetPPS.setSubPicIdMappingInPpsFlag(false);
// picture size
targetPPS.setPicWidthInLumaSamples(subPic.getSubPicWidthInLumaSample());
targetPPS.setPicHeightInLumaSamples(subPic.getSubPicHeightInLumaSample());
// todo: Conformance window
// Tiles
int numTileCols = 1;
int numTileRows = 1;
std::vector<uint32_t> tileColWidth;
std::vector<uint32_t> tileRowHeight;
std::vector<uint32_t> tileColBd;
std::vector<uint32_t> tileRowBd;
for (int i=0; i<= sourcePPS.getNumTileColumns(); i++)
{
const int currentColBd = sourcePPS.getTileColumnBd(i);
if ((currentColBd >= subPic.getSubPicCtuTopLeftX()) && (currentColBd <= (subPic.getSubPicCtuTopLeftX() + subPic.getSubPicWidthInCTUs())))
{
tileColBd.push_back(currentColBd - subPic.getSubPicCtuTopLeftX());
}
}
numTileCols=(int)tileColBd.size() - 1;

Karsten Suehring
committed
CHECK (numTileCols < 1, "After extraction there should be at least one tile horizonally.");
tileColWidth.resize(numTileCols);
for (int i=0; i<numTileCols; i++)
{
tileColWidth[i] = tileColBd[i+1] - tileColBd[i];
}
targetPPS.setNumExpTileColumns(numTileCols);
targetPPS.setNumTileColumns(numTileCols);
targetPPS.setTileColumnWidths(tileColWidth);
for (int i=0; i<= sourcePPS.getNumTileRows(); i++)
{
const int currentRowBd = sourcePPS.getTileRowBd(i);
if ((currentRowBd >= subPic.getSubPicCtuTopLeftY()) && (currentRowBd <= (subPic.getSubPicCtuTopLeftY() + subPic.getSubPicHeightInCTUs())))
{
tileRowBd.push_back(currentRowBd - subPic.getSubPicCtuTopLeftY());
}
}
numTileRows=(int)tileRowBd.size() - 1;

Karsten Suehring
committed
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// if subpicture was part of a tile, top and/or bottom borders need to be added
// note: this can only happen with vertical slice splits of a tile
if (numTileRows < 1 )
{
if (tileRowBd.size()==0)
{
tileRowBd.push_back(0);
tileRowBd.push_back(subPic.getSubPicHeightInCTUs());
numTileRows+=2;
}
else
{
if (tileRowBd[0] == 0)
{
// top border exists, add bottom
tileRowBd.push_back(subPic.getSubPicHeightInCTUs());
numTileRows++;
}
else
{
// bottom border exists, add top
const int row1 = tileRowBd[0];
tileRowBd[0] = 0;
tileRowBd.push_back(row1);
numTileRows++;
}
}
}
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
tileRowHeight.resize(numTileRows);
for (int i=0; i<numTileRows; i++)
{
tileRowHeight[i] = tileRowBd[i+1] - tileRowBd[i];
}
targetPPS.setNumExpTileRows(numTileRows);
targetPPS.setNumTileRows(numTileRows);
targetPPS.setTileRowHeights(tileRowHeight);
// slices
// no change reqired when each slice is one subpicture
if (!sourcePPS.getSingleSlicePerSubPicFlag())
{
int targetNumSlices = subPic.getNumSlicesInSubPic();
targetPPS.setNumSlicesInPic(targetNumSlices);
for (int i=0, cnt=0; i<sourcePPS.getNumSlicesInPic(); i++)
{
SliceMap slMap= sourcePPS.getSliceMap(i);
if (subPic.containsCtu(slMap.getCtuAddrInSlice(0)))
{
targetPPS.setSliceWidthInTiles(cnt, sourcePPS.getSliceWidthInTiles(i));
targetPPS.setSliceHeightInTiles(cnt, sourcePPS.getSliceHeightInTiles(i));
targetPPS.setNumSlicesInTile(cnt, sourcePPS.getNumSlicesInTile(i));
targetPPS.setSliceHeightInCtu(cnt, sourcePPS.getSliceHeightInCtu(i));
targetPPS.setSliceTileIdx(cnt, sourcePPS.getSliceTileIdx(i));
cnt++;
}
}
// renumber tiles to close gaps
for (int i=0; i<targetPPS.getNumSlicesInPic(); i++)
{
int minVal = MAX_INT;
int minPos = -1;
for (int j=0; j<targetPPS.getNumSlicesInPic(); j++)
{
if ((targetPPS.getSliceTileIdx(j) < minVal) && (targetPPS.getSliceTileIdx(j) >= i))
{
minVal = targetPPS.getSliceTileIdx(j);
minPos = j;
}
}
if ( minPos != -1)
{
targetPPS.setSliceTileIdx(minPos, i);
}
}
}
}
#endif
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
void BitstreamExtractorApp::xWriteVPS(VPS *vps, std::ostream& out, int layerId, int temporalId)
{
// create a new NAL unit for output
OutputNALUnit naluOut (NAL_UNIT_VPS, layerId, temporalId);
CHECK( naluOut.m_temporalId, "The value of TemporalId of VPS NAL units shall be equal to 0" );
// write the VPS to the newly created NAL unit buffer
m_hlSyntaxWriter.setBitstream( &naluOut.m_Bitstream );
m_hlSyntaxWriter.codeVPS( vps );
// create a dummy AU
AccessUnit tmpAu;
// convert to EBSP (this adds emulation prevention!) and add into NAL unit
tmpAu.push_back(new NALUnitEBSP(naluOut));
// write the dummy AU
// note: The first NAL unit in an access unit will be written with a 4-byte start code
// Parameter sets are also coded with a 4-byte start code, so writing the dummy
// AU works without chaning the start code length.
// This cannot be done for VLC NAL units!
writeAnnexB (out, tmpAu);
}
void BitstreamExtractorApp::xWriteSPS(SPS *sps, std::ostream& out, int layerId, int temporalId)
{
// create a new NAL unit for output
OutputNALUnit naluOut (NAL_UNIT_SPS, layerId, temporalId);
CHECK( naluOut.m_temporalId, "The value of TemporalId of SPS NAL units shall be equal to 0" );
// write the SPS to the newly created NAL unit buffer
m_hlSyntaxWriter.setBitstream( &naluOut.m_Bitstream );
m_hlSyntaxWriter.codeSPS( sps );
// create a dummy AU
AccessUnit tmpAu;
// convert to EBSP (this adds emulation prevention!) and add into NAL unit
tmpAu.push_back(new NALUnitEBSP(naluOut));
// write the dummy AU
// note: The first NAL unit in an access unit will be written with a 4-byte start code
// Parameter sets are also coded with a 4-byte start code, so writing the dummy
// AU works without chaning the start code length.
// This cannot be done for VLC NAL units!
writeAnnexB (out, tmpAu);
}
void BitstreamExtractorApp::xWritePPS(PPS *pps, std::ostream& out, int layerId, int temporalId)
{
// create a new NAL unit for output
OutputNALUnit naluOut (NAL_UNIT_PPS, layerId, temporalId);
// write the PPS to the newly created NAL unit buffer
m_hlSyntaxWriter.setBitstream( &naluOut.m_Bitstream );
m_hlSyntaxWriter.codePPS( pps );
// create a dummy AU
AccessUnit tmpAu;
// convert to EBSP (this adds emulation prevention!) and add into NAL unit
tmpAu.push_back(new NALUnitEBSP(naluOut));
// write the dummy AU
// note: The first NAL unit in an access unit will be written with a 4-byte start code
// Parameter sets are also coded with a 4-byte start code, so writing the dummy
// AU works without chaning the start code length.
// This cannot be done for VLC NAL units!
writeAnnexB (out, tmpAu);
}
uint32_t BitstreamExtractorApp::decode()
{
std::ifstream bitstreamFileIn(m_bitstreamFileNameIn.c_str(), std::ifstream::in | std::ifstream::binary);
if (!bitstreamFileIn)
{
EXIT( "failed to open bitstream file " << m_bitstreamFileNameIn.c_str() << " for reading" ) ;
}
std::ofstream bitstreamFileOut(m_bitstreamFileNameOut.c_str(), std::ifstream::out | std::ifstream::binary);
InputByteStream bytestream(bitstreamFileIn);
bitstreamFileIn.clear();
bitstreamFileIn.seekg( 0, std::ios::beg );
int unitCnt = 0;
VPS *vpsIdZero = new VPS();
std::vector<uint8_t> empty;
m_parameterSetManager.storeVPS(vpsIdZero, empty);
while (!!bitstreamFileIn)
{
AnnexBStats stats = AnnexBStats();
InputNALUnit nalu;
byteStreamNALUnit(bytestream, nalu.getBitstream().getFifo(), stats);
// call actual decoding function
if (nalu.getBitstream().getFifo().empty())
{
/* this can happen if the following occur:
* - empty input file
* - two back-to-back start_code_prefixes
* - start_code_prefix immediately followed by EOF
*/
msg(WARNING, "Warning: Attempt to decode an empty NAL unit" );
}
else
{
read(nalu);
bool writeInpuNalUnitToStream = true;
// Remove NAL units with TemporalId greater than tIdTarget.
writeInpuNalUnitToStream &= ( m_maxTemporalLayer < 0 ) || ( nalu.m_temporalId <= m_maxTemporalLayer );
if( nalu.m_nalUnitType == NAL_UNIT_VPS )
{
VPS* vps = new VPS();
m_hlSynaxReader.setBitstream( &nalu.getBitstream() );
m_hlSynaxReader.parseVPS( vps );
int vpsId = vps->getVPSId();
// note: storeVPS may invalidate the vps pointer!
m_parameterSetManager.storeVPS( vps, nalu.getBitstream().getFifo() );
// get VPS back
vps = m_parameterSetManager.getVPS(vpsId);
xPrintVPSInfo(vps);
#if JVET_P0118_OLS_EXTRACTION
m_vpsId = vps->getVPSId();
#endif
// example: just write the parsed VPS back to the stream
// *** add modifications here ***
// only write, if not dropped earlier
if (writeInpuNalUnitToStream)
{
xWriteVPS(vps, bitstreamFileOut, nalu.m_nuhLayerId, nalu.m_temporalId);
writeInpuNalUnitToStream = false;
}
}
// if there is no VPS nal unit, there shall be one OLS and one layer.
if (m_vpsId == -1)
{
CHECK(m_targetOlsIdx != 0, "only one OLS and one layer exist, but target olsIdx is not equal to zero");
vps = new VPS();
vps->setNumLayersInOls(0, 1);
vps->setLayerIdInOls(0, 0, nalu.m_nuhLayerId);
}
else
{
// Remove NAL units with nal_unit_type not equal to any of VPS_NUT, DPS_NUT, and EOB_NUT and with nuh_layer_id not included in the list LayerIdInOls[targetOlsIdx].
NalUnitType t = nalu.m_nalUnitType;
bool isSpecialNalTypes = t == NAL_UNIT_VPS || t == NAL_UNIT_DCI || t == NAL_UNIT_EOB;
vps = m_parameterSetManager.getVPS(m_vpsId);
uint32_t numOlss = vps->getNumOutputLayerSets();
CHECK(m_targetOlsIdx <0 || m_targetOlsIdx >= numOlss, "target Ols shall be in the range of OLSs specified by the VPS");
std::vector<int> LayerIdInOls = vps->getLayerIdsInOls(m_targetOlsIdx);
bool isIncludedInTargetOls = std::find(LayerIdInOls.begin(), LayerIdInOls.end(), nalu.m_nuhLayerId) != LayerIdInOls.end();
writeInpuNalUnitToStream &= (isSpecialNalTypes || isIncludedInTargetOls);
}
if( nalu.m_nalUnitType == NAL_UNIT_SPS )
{
SPS* sps = new SPS();
m_hlSynaxReader.setBitstream( &nalu.getBitstream() );
m_hlSynaxReader.parseSPS( sps );
int spsId = sps->getSPSId();
// note: storeSPS may invalidate the sps pointer!
m_parameterSetManager.storeSPS( sps, nalu.getBitstream().getFifo() );
// get SPS back
sps = m_parameterSetManager.getSPS(spsId);
msg (VERBOSE, "SPS Info: SPS ID = %d\n", spsId);
// example: just write the parsed SPS back to the stream
// *** add modifications here ***
// only write, if not dropped earlier
// rewrite the SPS
#if JVET_Q0397_SUB_PIC_EXTRACT
if (m_subPicId >= 0)
{
// we generally don't write SPS to the bitstream unless referred to by PPS
// but remember that the SPS got updated
xSetSPSUpdated(sps->getSPSId());
writeInpuNalUnitToStream = false;
}
#endif
if (writeInpuNalUnitToStream)
{
xWriteSPS(sps, bitstreamFileOut, nalu.m_nuhLayerId, nalu.m_temporalId);
writeInpuNalUnitToStream = false;
}
}
if( nalu.m_nalUnitType == NAL_UNIT_PPS )
{
PPS* pps = new PPS();
m_hlSynaxReader.setBitstream( &nalu.getBitstream() );
m_hlSynaxReader.parsePPS( pps );
int ppsId = pps->getPPSId();
// note: storePPS may invalidate the pps pointer!
m_parameterSetManager.storePPS( pps, nalu.getBitstream().getFifo() );
// get PPS back
pps = m_parameterSetManager.getPPS(ppsId);
msg (VERBOSE, "PPS Info: PPS ID = %d\n", pps->getPPSId());
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
#if JVET_Q0397_SUB_PIC_EXTRACT
SPS *sps = m_parameterSetManager.getSPS(pps->getSPSId());
if ( nullptr == sps)
{
printf("Cannot find SPS referred to by PPS, ignoring");
}
else
{
pps->initSubPic(*sps);
xPrintSubPicInfo (pps);
if (m_subPicId >= 0)
{
SubPic subPic;
bool found = false;
for (int i=0; i< pps->getNumSubPics() && !found; i++)
{
subPic = pps->getSubPic(i);
if (subPic.getSubPicID() == m_subPicId)
{
found=true;
}
}
CHECK (!found, "Target subpicture not found");
// if the referred SPS was updated, modify and write it
if (xIsSPSUpdate(sps->getSPSId()))
{
SPS targetSPS;
xRewriteSPS(targetSPS, *sps, subPic);
xWriteSPS(&targetSPS, bitstreamFileOut, nalu.m_nuhLayerId, nalu.m_temporalId);
xClearSPSUpdated(sps->getSPSId());
}
// rewrite the PPS
PPS targetPPS;
xRewritePPS(targetPPS, *pps, subPic);
xWritePPS(&targetPPS, bitstreamFileOut, nalu.m_nuhLayerId, nalu.m_temporalId);
writeInpuNalUnitToStream = false;
}
}
#endif
// example: just write the parsed PPS back to the stream
// *** add modifications here ***
// only write, if not dropped earlier
if (writeInpuNalUnitToStream)
{
xWritePPS(pps, bitstreamFileOut, nalu.m_nuhLayerId, nalu.m_temporalId);
writeInpuNalUnitToStream = false;
}
}
#if JVET_Q0397_SUB_PIC_EXTRACT
// when re-using code for slice header parsing, we need to store APSs
if( ( nalu.m_nalUnitType == NAL_UNIT_PREFIX_APS ) || ( nalu.m_nalUnitType == NAL_UNIT_SUFFIX_APS ))
{
APS* aps = new APS();
m_hlSynaxReader.setBitstream( &nalu.getBitstream() );
m_hlSynaxReader.parseAPS( aps );
int apsId = aps->getAPSId();
int apsType = aps->getAPSType();
// note: storeAPS may invalidate the aps pointer!
m_parameterSetManager.storeAPS( aps, nalu.getBitstream().getFifo() );
// get APS back
aps = m_parameterSetManager.getAPS(apsId, apsType);
}
if (nalu.m_nalUnitType == NAL_UNIT_PH)
{
xReadPicHeader(nalu);
}
#endif
if (nalu.m_nalUnitType == NAL_UNIT_PREFIX_SEI)
// decoding a SEI
SEIMessages SEIs;
HRD hrd;
m_seiReader.parseSEImessage(&(nalu.getBitstream()), SEIs, nalu.m_nalUnitType, nalu.m_nuhLayerId, nalu.m_temporalId, vps, m_parameterSetManager.getActiveSPS(), hrd, &std::cout);
for (auto sei : SEIs)
// remove unqualiified scalable nesting SEI
if (sei->payloadType() == SEI::SCALABLE_NESTING)
SEIScalableNesting *seiNesting = (SEIScalableNesting *)sei;
if (seiNesting->m_nestingOlsFlag == 1)
bool targetOlsIdxInNestingAppliedOls = false;
for (uint32_t i = 0; i <= seiNesting->m_nestingNumOlssMinus1; i++)
if (seiNesting->m_nestingOlsIdx[i] == m_targetOlsIdx)
{
targetOlsIdxInNestingAppliedOls = true;
break;
}
writeInpuNalUnitToStream &= targetOlsIdxInNestingAppliedOls;
}
// remove unqualified timing related SEI
if (sei->payloadType() == SEI::BUFFERING_PERIOD || sei->payloadType() == SEI::PICTURE_TIMING || sei->payloadType() == SEI::DECODING_UNIT_INFO)
{
bool targetOlsIdxGreaterThanZero = m_targetOlsIdx > 0;
writeInpuNalUnitToStream &= !targetOlsIdxGreaterThanZero;
}
if (m_vpsId == -1)
{
delete vps;
#endif
#if JVET_Q0397_SUB_PIC_EXTRACT
if (m_subPicId>=0)
{
if ( nalu.isSlice() )
{
// check for subpicture ID
writeInpuNalUnitToStream = xCheckSliceSubpicture(nalu, m_subPicId);
}
}
unitCnt++;
if( writeInpuNalUnitToStream )
{
int numZeros = stats.m_numLeadingZero8BitsBytes + stats.m_numZeroByteBytes + stats.m_numStartCodePrefixBytes -1;
// write start code
char ch = 0;
for( int i = 0 ; i < numZeros; i++ )
{
bitstreamFileOut.write( &ch, 1 );
}
ch = 1;
bitstreamFileOut.write( &ch, 1 );
// write input NAL unit
bitstreamFileOut.write( (const char*)nalu.getBitstream().getFifo().data(), nalu.getBitstream().getFifo().size() );
}
}
}
return 0;
}