1 /*!
2 * \copy
3 * Copyright (c) 2009-2013, Cisco Systems
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *
32 * \file au_set.c
33 *
34 * \brief Interfaces introduced in Access Unit level based writer
35 *
36 * \date 05/18/2009 Created
37 *
38 *************************************************************************************
39 */
40
41 #include "au_set.h"
42 #include "svc_enc_golomb.h"
43 #include "macros.h"
44
45 #include "wels_common_defs.h"
46
47 using namespace WelsCommon;
48
49 namespace WelsEnc {
50
WelsCheckLevelLimitation(const SWelsSPS * kpSps,const SLevelLimits * kpLevelLimit,float fFrameRate,int32_t iTargetBitRate)51 static inline int32_t WelsCheckLevelLimitation (const SWelsSPS* kpSps, const SLevelLimits* kpLevelLimit,
52 float fFrameRate, int32_t iTargetBitRate) {
53 uint32_t uiPicWidthInMBs = kpSps->iMbWidth;
54 uint32_t uiPicHeightInMBs = kpSps->iMbHeight;
55 uint32_t uiPicInMBs = uiPicWidthInMBs * uiPicHeightInMBs;
56 uint32_t uiNumRefFrames = kpSps->iNumRefFrames;
57
58 if (kpLevelLimit->uiMaxMBPS < (uint32_t) (uiPicInMBs * fFrameRate))
59 return 0;
60 if (kpLevelLimit->uiMaxFS < uiPicInMBs)
61 return 0;
62 if ((kpLevelLimit->uiMaxFS << 3) < (uiPicWidthInMBs * uiPicWidthInMBs))
63 return 0;
64 if ((kpLevelLimit->uiMaxFS << 3) < (uiPicHeightInMBs * uiPicHeightInMBs))
65 return 0;
66 if (kpLevelLimit->uiMaxDPBMbs < uiNumRefFrames * uiPicInMBs)
67 return 0;
68 if ((iTargetBitRate != UNSPECIFIED_BIT_RATE)
69 && ((int32_t) kpLevelLimit->uiMaxBR * 1200) < iTargetBitRate) //RC enabled, considering bitrate constraint
70 return 0;
71 //add more checks here if needed in future
72
73 return 1;
74
75 }
WelsAdjustLevel(SSpatialLayerConfig * pSpatialLayer,const SLevelLimits * pCurLevel)76 int32_t WelsAdjustLevel (SSpatialLayerConfig* pSpatialLayer, const SLevelLimits* pCurLevel) {
77 int32_t iMaxBitrate = pSpatialLayer->iMaxSpatialBitrate;
78 do {
79 if (iMaxBitrate <= (int32_t) (pCurLevel->uiMaxBR * CpbBrNalFactor)) {
80 pSpatialLayer->uiLevelIdc = pCurLevel->uiLevelIdc;
81 return 0;
82 }
83 pCurLevel++;
84 } while (pCurLevel->uiLevelIdc != LEVEL_5_2);
85 return 1;
86 }
87
WelsCheckNumRefSetting(SLogContext * pLogCtx,SWelsSvcCodingParam * pParam,bool bStrictCheck)88 static int32_t WelsCheckNumRefSetting (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, bool bStrictCheck) {
89 // validate LTR num
90 int32_t iCurrentSupportedLtrNum = (pParam->iUsageType == CAMERA_VIDEO_REAL_TIME) ? LONG_TERM_REF_NUM :
91 LONG_TERM_REF_NUM_SCREEN;
92 if ((pParam->bEnableLongTermReference) && (iCurrentSupportedLtrNum != pParam->iLTRRefNum)) {
93 WelsLog (pLogCtx, WELS_LOG_WARNING, "iLTRRefNum(%d) does not equal to currently supported %d, will be reset",
94 pParam->iLTRRefNum, iCurrentSupportedLtrNum);
95 pParam->iLTRRefNum = iCurrentSupportedLtrNum;
96 } else if (!pParam->bEnableLongTermReference) {
97 pParam->iLTRRefNum = 0;
98 }
99
100 //TODO: here is a fix needed here, the most reasonable value should be:
101 // iCurrentStrNum = WELS_MAX (1, WELS_LOG2 (pParam->uiGopSize));
102 // but reference list updating need to be changed
103 int32_t iCurrentStrNum = ((pParam->iUsageType == SCREEN_CONTENT_REAL_TIME && pParam->bEnableLongTermReference)
104 ? (WELS_MAX (1, WELS_LOG2 (pParam->uiGopSize)))
105 : (WELS_MAX (1, (pParam->uiGopSize >> 1))));
106 int32_t iNeededRefNum = (pParam->uiIntraPeriod != 1) ? (iCurrentStrNum + pParam->iLTRRefNum) : 0;
107
108 iNeededRefNum = WELS_CLIP3 (iNeededRefNum,
109 MIN_REF_PIC_COUNT,
110 (pParam->iUsageType == CAMERA_VIDEO_REAL_TIME) ? MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA :
111 MAX_REFERENCE_PICTURE_COUNT_NUM_SCREEN);
112 // to adjust default or invalid input, in case pParam->iNumRefFrame do not have a valid value for the next step
113 if (pParam->iNumRefFrame == AUTO_REF_PIC_COUNT) {
114 pParam->iNumRefFrame = iNeededRefNum;
115 } else if (pParam->iNumRefFrame < iNeededRefNum) {
116 WelsLog (pLogCtx, WELS_LOG_WARNING,
117 "iNumRefFrame(%d) setting does not support the temporal and LTR setting, will be reset to %d",
118 pParam->iNumRefFrame, iNeededRefNum);
119 if (bStrictCheck) {
120 return ENC_RETURN_UNSUPPORTED_PARA;
121 }
122 pParam->iNumRefFrame = iNeededRefNum;
123 }
124
125 // after adjustment, do the following:
126 // if the setting is larger than needed, we will use the needed, and write the max into sps and for memory to wait for further expanding
127 if (pParam->iMaxNumRefFrame < pParam->iNumRefFrame) {
128 pParam->iMaxNumRefFrame = pParam->iNumRefFrame;
129 }
130 pParam->iNumRefFrame = iNeededRefNum;
131
132 return ENC_RETURN_SUCCESS;
133 }
134
WelsCheckRefFrameLimitationNumRefFirst(SLogContext * pLogCtx,SWelsSvcCodingParam * pParam)135 int32_t WelsCheckRefFrameLimitationNumRefFirst (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam) {
136
137 if (WelsCheckNumRefSetting (pLogCtx, pParam, false)) {
138 // we take num-ref as the honored setting but it conflicts with temporal and LTR
139 return ENC_RETURN_UNSUPPORTED_PARA;
140 }
141 return ENC_RETURN_SUCCESS;
142 }
WelsCheckRefFrameLimitationLevelIdcFirst(SLogContext * pLogCtx,SWelsSvcCodingParam * pParam)143 int32_t WelsCheckRefFrameLimitationLevelIdcFirst (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam) {
144 if ((pParam->iNumRefFrame == AUTO_REF_PIC_COUNT) || (pParam->iMaxNumRefFrame == AUTO_REF_PIC_COUNT)) {
145 //no need to do the checking
146 return ENC_RETURN_SUCCESS;
147 }
148
149 WelsCheckNumRefSetting (pLogCtx, pParam, false);
150
151 int32_t i = 0;
152 int32_t iRefFrame;
153 //get the number of reference frame according to level limitation.
154 for (i = 0; i < pParam->iSpatialLayerNum; ++ i) {
155 SSpatialLayerConfig* pSpatialLayer = &pParam->sSpatialLayers[i];
156 if (pSpatialLayer->uiLevelIdc == LEVEL_UNKNOWN) {
157 continue;
158 }
159
160 uint32_t uiPicInMBs = ((pSpatialLayer->iVideoHeight + 15) >> 4) * ((pSpatialLayer->iVideoWidth + 15) >> 4);
161 iRefFrame = g_ksLevelLimits[pSpatialLayer->uiLevelIdc - 1].uiMaxDPBMbs / uiPicInMBs;
162
163 //check iMaxNumRefFrame
164 if (iRefFrame < pParam->iMaxNumRefFrame) {
165 WelsLog (pLogCtx, WELS_LOG_WARNING, "iMaxNumRefFrame(%d) adjusted to %d because of limitation from uiLevelIdc=%d",
166 pParam->iMaxNumRefFrame, iRefFrame, pSpatialLayer->uiLevelIdc);
167 pParam->iMaxNumRefFrame = iRefFrame;
168
169 //check iNumRefFrame
170 if (iRefFrame < pParam->iNumRefFrame) {
171 WelsLog (pLogCtx, WELS_LOG_WARNING, "iNumRefFrame(%d) adjusted to %d because of limitation from uiLevelIdc=%d",
172 pParam->iNumRefFrame, iRefFrame, pSpatialLayer->uiLevelIdc);
173 pParam->iNumRefFrame = iRefFrame;
174 }
175 } else {
176 //because it is level first now, so adjust max-ref
177 WelsLog (pLogCtx, WELS_LOG_INFO,
178 "iMaxNumRefFrame(%d) adjusted to %d because of uiLevelIdc=%d -- under level-idc first strategy ",
179 pParam->iMaxNumRefFrame, iRefFrame, pSpatialLayer->uiLevelIdc);
180 pParam->iMaxNumRefFrame = iRefFrame;
181 }
182 }
183
184 return ENC_RETURN_SUCCESS;
185 }
186
WelsGetLevelIdc(const SWelsSPS * kpSps,float fFrameRate,int32_t iTargetBitRate)187 static inline ELevelIdc WelsGetLevelIdc (const SWelsSPS* kpSps, float fFrameRate, int32_t iTargetBitRate) {
188 int32_t iOrder;
189 for (iOrder = 0; iOrder < LEVEL_NUMBER; iOrder++) {
190 if (WelsCheckLevelLimitation (kpSps, & (g_ksLevelLimits[iOrder]), fFrameRate, iTargetBitRate)) {
191 return (g_ksLevelLimits[iOrder].uiLevelIdc);
192 }
193 }
194 return LEVEL_5_1; //final decision: select the biggest level
195 }
196
WelsWriteVUI(SWelsSPS * pSps,SBitStringAux * pBitStringAux)197 int32_t WelsWriteVUI (SWelsSPS* pSps, SBitStringAux* pBitStringAux) {
198 SBitStringAux* pLocalBitStringAux = pBitStringAux;
199 assert (pSps != NULL && pBitStringAux != NULL);
200
201 BsWriteOneBit (pLocalBitStringAux, pSps->bAspectRatioPresent); //aspect_ratio_info_present_flag
202 if (pSps->bAspectRatioPresent) {
203 BsWriteBits (pLocalBitStringAux, 8, pSps->eAspectRatio); // aspect_ratio_idc
204 if (pSps->eAspectRatio == ASP_EXT_SAR) {
205 BsWriteBits (pLocalBitStringAux, 16, pSps->sAspectRatioExtWidth); // sar_width
206 BsWriteBits (pLocalBitStringAux, 16, pSps->sAspectRatioExtHeight); // sar_height
207 }
208 }
209 BsWriteOneBit (pLocalBitStringAux, false); //overscan_info_present_flag
210
211 // See codec_app_def.h and parameter_sets.h for more info about members bVideoSignalTypePresent through uiColorMatrix.
212 BsWriteOneBit (pLocalBitStringAux, pSps->bVideoSignalTypePresent); //video_signal_type_present_flag
213 if (pSps->bVideoSignalTypePresent) {
214 //write video signal type info to header
215
216 BsWriteBits (pLocalBitStringAux, 3, pSps->uiVideoFormat);
217 BsWriteOneBit (pLocalBitStringAux, pSps->bFullRange);
218 BsWriteOneBit (pLocalBitStringAux, pSps->bColorDescriptionPresent);
219
220 if (pSps->bColorDescriptionPresent) {
221 //write color description info to header
222
223 BsWriteBits (pLocalBitStringAux, 8, pSps->uiColorPrimaries);
224 BsWriteBits (pLocalBitStringAux, 8, pSps->uiTransferCharacteristics);
225 BsWriteBits (pLocalBitStringAux, 8, pSps->uiColorMatrix);
226
227 }//write color description info to header
228
229 }//write video signal type info to header
230
231 BsWriteOneBit (pLocalBitStringAux, false); //chroma_loc_info_present_flag
232 BsWriteOneBit (pLocalBitStringAux, false); //timing_info_present_flag
233 BsWriteOneBit (pLocalBitStringAux, false); //nal_hrd_parameters_present_flag
234 BsWriteOneBit (pLocalBitStringAux, false); //vcl_hrd_parameters_present_flag
235 BsWriteOneBit (pLocalBitStringAux, false); //pic_struct_present_flag
236 BsWriteOneBit (pLocalBitStringAux, true); //bitstream_restriction_flag
237
238 //
239 BsWriteOneBit (pLocalBitStringAux, true); //motion_vectors_over_pic_boundaries_flag
240 BsWriteUE (pLocalBitStringAux, 0); //max_bytes_per_pic_denom
241 BsWriteUE (pLocalBitStringAux, 0); //max_bits_per_mb_denom
242 BsWriteUE (pLocalBitStringAux, 16); //log2_max_mv_length_horizontal
243 BsWriteUE (pLocalBitStringAux, 16); //log2_max_mv_length_vertical
244
245 BsWriteUE (pLocalBitStringAux, 0); //max_num_reorder_frames
246 BsWriteUE (pLocalBitStringAux, pSps->iNumRefFrames); //max_dec_frame_buffering
247
248 return 0;
249 }
250
251 /*!
252 *************************************************************************************
253 * \brief to set Sequence Parameter Set (SPS)
254 *
255 * \param pSps SWelsSPS to be wrote, update iSpsId dependency
256 * \param pBitStringAux bitstream writer auxiliary
257 *
258 * \return 0 - successed
259 * 1 - failed
260 *
261 * \note Call it in case EWelsNalUnitType is SPS.
262 *************************************************************************************
263 */
WelsWriteSpsSyntax(SWelsSPS * pSps,SBitStringAux * pBitStringAux,int32_t * pSpsIdDelta,bool bBaseLayer)264 int32_t WelsWriteSpsSyntax (SWelsSPS* pSps, SBitStringAux* pBitStringAux, int32_t* pSpsIdDelta, bool bBaseLayer) {
265 SBitStringAux* pLocalBitStringAux = pBitStringAux;
266
267 assert (pSps != NULL && pBitStringAux != NULL);
268
269 BsWriteBits (pLocalBitStringAux, 8, pSps->uiProfileIdc);
270
271 BsWriteOneBit (pLocalBitStringAux, pSps->bConstraintSet0Flag); // bConstraintSet0Flag
272 BsWriteOneBit (pLocalBitStringAux, pSps->bConstraintSet1Flag); // bConstraintSet1Flag
273 BsWriteOneBit (pLocalBitStringAux, pSps->bConstraintSet2Flag); // bConstraintSet2Flag
274 BsWriteOneBit (pLocalBitStringAux, pSps->bConstraintSet3Flag); // bConstraintSet3Flag
275 if (PRO_HIGH == pSps->uiProfileIdc || PRO_EXTENDED == pSps->uiProfileIdc ||
276 PRO_MAIN == pSps->uiProfileIdc) {
277 BsWriteOneBit (pLocalBitStringAux, 1); // bConstraintSet4Flag: If profile_idc is equal to 77, 88, or 100, constraint_set4_flag equal to 1 indicates that the value of frame_mbs_only_flag is equal to 1. constraint_set4_flag equal to 0 indicates that the value of frame_mbs_only_flag may or may not be equal to 1.
278 BsWriteOneBit (pLocalBitStringAux, 1); // bConstraintSet5Flag: If profile_idc is equal to 77, 88, or 100, constraint_set5_flag equal to 1 indicates that B slice types are not present in the coded video sequence. constraint_set5_flag equal to 0 indicates that B slice types may or may not be present in the coded video sequence.
279 BsWriteBits (pLocalBitStringAux, 2, 0); // reserved_zero_2bits, equal to 0
280 } else {
281 BsWriteBits (pLocalBitStringAux, 4, 0); // reserved_zero_4bits, equal to 0
282 }
283 BsWriteBits (pLocalBitStringAux, 8, pSps->iLevelIdc); // iLevelIdc
284 BsWriteUE (pLocalBitStringAux, pSps->uiSpsId + pSpsIdDelta[pSps->uiSpsId]); // seq_parameter_set_id
285
286 if (PRO_SCALABLE_BASELINE == pSps->uiProfileIdc || PRO_SCALABLE_HIGH == pSps->uiProfileIdc ||
287 PRO_HIGH == pSps->uiProfileIdc || PRO_HIGH10 == pSps->uiProfileIdc ||
288 PRO_HIGH422 == pSps->uiProfileIdc || PRO_HIGH444 == pSps->uiProfileIdc ||
289 PRO_CAVLC444 == pSps->uiProfileIdc || 44 == pSps->uiProfileIdc) {
290 BsWriteUE (pLocalBitStringAux, 1); //uiChromaFormatIdc, now should be 1
291 BsWriteUE (pLocalBitStringAux, 0); //uiBitDepthLuma
292 BsWriteUE (pLocalBitStringAux, 0); //uiBitDepthChroma
293 BsWriteOneBit (pLocalBitStringAux, 0); //qpprime_y_zero_transform_bypass_flag
294 BsWriteOneBit (pLocalBitStringAux, 0); //seq_scaling_matrix_present_flag
295 }
296
297 BsWriteUE (pLocalBitStringAux, pSps->uiLog2MaxFrameNum - 4); // log2_max_frame_num_minus4
298 BsWriteUE (pLocalBitStringAux, 0/*pSps->uiPocType*/); // pic_order_cnt_type
299 BsWriteUE (pLocalBitStringAux, pSps->iLog2MaxPocLsb - 4); // log2_max_pic_order_cnt_lsb_minus4
300
301 BsWriteUE (pLocalBitStringAux, pSps->iNumRefFrames); // max_num_ref_frames
302 BsWriteOneBit (pLocalBitStringAux, pSps->bGapsInFrameNumValueAllowedFlag); //gaps_in_frame_numvalue_allowed_flag
303 BsWriteUE (pLocalBitStringAux, pSps->iMbWidth - 1); // pic_width_in_mbs_minus1
304 BsWriteUE (pLocalBitStringAux, pSps->iMbHeight - 1); // pic_height_in_map_units_minus1
305 BsWriteOneBit (pLocalBitStringAux, true/*pSps->bFrameMbsOnlyFlag*/); // bFrameMbsOnlyFlag
306
307 uint8_t d8x8 = 0;
308 if (pSps->iLevelIdc >= 30)
309 d8x8 = 1;
310 BsWriteOneBit (pLocalBitStringAux, d8x8/*pSps->bDirect8x8InferenceFlag*/); // direct_8x8_inference_flag
311
312 BsWriteOneBit (pLocalBitStringAux, pSps->bFrameCroppingFlag); // bFrameCroppingFlag
313 if (pSps->bFrameCroppingFlag) {
314 BsWriteUE (pLocalBitStringAux, pSps->sFrameCrop.iCropLeft); // frame_crop_left_offset
315 BsWriteUE (pLocalBitStringAux, pSps->sFrameCrop.iCropRight); // frame_crop_right_offset
316 BsWriteUE (pLocalBitStringAux, pSps->sFrameCrop.iCropTop); // frame_crop_top_offset
317 BsWriteUE (pLocalBitStringAux, pSps->sFrameCrop.iCropBottom); // frame_crop_bottom_offset
318 }
319 if (bBaseLayer) {
320 BsWriteOneBit (pLocalBitStringAux, true); // vui_parameters_present_flag
321 WelsWriteVUI (pSps, pBitStringAux);
322 } else {
323 BsWriteOneBit (pLocalBitStringAux, false);
324 }
325 return 0;
326 }
327
328
WelsWriteSpsNal(SWelsSPS * pSps,SBitStringAux * pBitStringAux,int32_t * pSpsIdDelta)329 int32_t WelsWriteSpsNal (SWelsSPS* pSps, SBitStringAux* pBitStringAux, int32_t* pSpsIdDelta) {
330 WelsWriteSpsSyntax (pSps, pBitStringAux, pSpsIdDelta, true);
331
332 BsRbspTrailingBits (pBitStringAux);
333
334 return 0;
335 }
336
337 /*!
338 *************************************************************************************
339 * \brief to write SubSet Sequence Parameter Set
340 *
341 * \param sub_sps subset pSps parsed
342 * \param pBitStringAux bitstream writer auxiliary
343 *
344 * \return 0 - successed
345 * 1 - failed
346 *
347 * \note Call it in case EWelsNalUnitType is SubSet SPS.
348 *************************************************************************************
349 */
350
WelsWriteSubsetSpsSyntax(SSubsetSps * pSubsetSps,SBitStringAux * pBitStringAux,int32_t * pSpsIdDelta)351 int32_t WelsWriteSubsetSpsSyntax (SSubsetSps* pSubsetSps, SBitStringAux* pBitStringAux , int32_t* pSpsIdDelta) {
352 SWelsSPS* pSps = &pSubsetSps->pSps;
353
354 WelsWriteSpsSyntax (pSps, pBitStringAux, pSpsIdDelta, false);
355
356 if (pSps->uiProfileIdc == PRO_SCALABLE_BASELINE || pSps->uiProfileIdc == PRO_SCALABLE_HIGH) {
357 SSpsSvcExt* pSubsetSpsExt = &pSubsetSps->sSpsSvcExt;
358
359 BsWriteOneBit (pBitStringAux, true/*pSubsetSpsExt->bInterLayerDeblockingFilterCtrlPresentFlag*/);
360 BsWriteBits (pBitStringAux, 2, pSubsetSpsExt->iExtendedSpatialScalability);
361 BsWriteOneBit (pBitStringAux, 0/*pSubsetSpsExt->uiChromaPhaseXPlus1Flag*/);
362 BsWriteBits (pBitStringAux, 2, 1/*pSubsetSpsExt->uiChromaPhaseYPlus1*/);
363 if (pSubsetSpsExt->iExtendedSpatialScalability == 1) {
364 BsWriteOneBit (pBitStringAux, 0/*pSubsetSpsExt->uiSeqRefLayerChromaPhaseXPlus1Flag*/);
365 BsWriteBits (pBitStringAux, 2, 1/*pSubsetSpsExt->uiSeqRefLayerChromaPhaseYPlus1*/);
366 BsWriteSE (pBitStringAux, 0/*pSubsetSpsExt->sSeqScaledRefLayer.left_offset*/);
367 BsWriteSE (pBitStringAux, 0/*pSubsetSpsExt->sSeqScaledRefLayer.top_offset*/);
368 BsWriteSE (pBitStringAux, 0/*pSubsetSpsExt->sSeqScaledRefLayer.right_offset*/);
369 BsWriteSE (pBitStringAux, 0/*pSubsetSpsExt->sSeqScaledRefLayer.bottom_offset*/);
370 }
371 BsWriteOneBit (pBitStringAux, pSubsetSpsExt->bSeqTcoeffLevelPredFlag);
372 if (pSubsetSpsExt->bSeqTcoeffLevelPredFlag) {
373 BsWriteOneBit (pBitStringAux, pSubsetSpsExt->bAdaptiveTcoeffLevelPredFlag);
374 }
375 BsWriteOneBit (pBitStringAux, pSubsetSpsExt->bSliceHeaderRestrictionFlag);
376
377 BsWriteOneBit (pBitStringAux, false/*pSubsetSps->bSvcVuiParamPresentFlag*/);
378 }
379 BsWriteOneBit (pBitStringAux, false/*pSubsetSps->bAdditionalExtension2Flag*/);
380
381 BsRbspTrailingBits (pBitStringAux);
382
383 return 0;
384 }
385
386 /*!
387 *************************************************************************************
388 * \brief to write Picture Parameter Set (PPS)
389 *
390 * \param pPps pPps
391 * \param pBitStringAux bitstream writer auxiliary
392 *
393 * \return 0 - successed
394 * 1 - failed
395 *
396 * \note Call it in case EWelsNalUnitType is PPS.
397 *************************************************************************************
398 */
WelsWritePpsSyntax(SWelsPPS * pPps,SBitStringAux * pBitStringAux,IWelsParametersetStrategy * pParametersetStrategy)399 int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux,
400 IWelsParametersetStrategy* pParametersetStrategy) {
401 SBitStringAux* pLocalBitStringAux = pBitStringAux;
402
403 BsWriteUE (pLocalBitStringAux, pPps->iPpsId + pParametersetStrategy->GetPpsIdOffset (pPps->iPpsId));
404 BsWriteUE (pLocalBitStringAux, pPps->iSpsId + pParametersetStrategy->GetSpsIdOffset (pPps->iPpsId, pPps->iSpsId));
405
406 BsWriteOneBit (pLocalBitStringAux, pPps->bEntropyCodingModeFlag);
407 BsWriteOneBit (pLocalBitStringAux, false/*pPps->bPicOrderPresentFlag*/);
408
409 #ifdef DISABLE_FMO_FEATURE
410 BsWriteUE (pLocalBitStringAux, 0/*pPps->uiNumSliceGroups - 1*/);
411 #else
412 BsWriteUE (pLocalBitStringAux, pPps->uiNumSliceGroups - 1);
413 if (pPps->uiNumSliceGroups > 1) {
414 uint32_t i, uiNumBits;
415
416 BsWriteUE (pLocalBitStringAux, pPps->uiSliceGroupMapType);
417
418 switch (pPps->uiSliceGroupMapType) {
419 case 0:
420 for (i = 0; i < pPps->uiNumSliceGroups; i ++) {
421 BsWriteUE (pLocalBitStringAux, pPps->uiRunLength[i] - 1);
422 }
423 break;
424 case 2:
425 for (i = 0; i < pPps->uiNumSliceGroups; i ++) {
426 BsWriteUE (pLocalBitStringAux, pPps->uiTopLeft[i]);
427 BsWriteUE (pLocalBitStringAux, pPps->uiBottomRight[i]);
428 }
429 break;
430 case 3:
431 case 4:
432 case 5:
433 BsWriteOneBit (pLocalBitStringAux, pPps->bSliceGroupChangeDirectionFlag);
434 BsWriteUE (pLocalBitStringAux, pPps->uiSliceGroupChangeRate - 1);
435 break;
436 case 6:
437 BsWriteUE (pLocalBitStringAux, pPps->uiPicSizeInMapUnits - 1);
438 uiNumBits = 0;///////////////////WELS_CEILLOG2(pPps->uiPicSizeInMapUnits);
439 for (i = 0; i < pPps->uiPicSizeInMapUnits; i ++) {
440 BsWriteBits (pLocalBitStringAux, uiNumBits, pPps->uiSliceGroupId[i]);
441 }
442 break;
443 default:
444 break;
445 }
446 }
447 #endif//!DISABLE_FMO_FEATURE
448
449 BsWriteUE (pLocalBitStringAux, 0/*pPps->uiNumRefIdxL0Active - 1*/);
450 BsWriteUE (pLocalBitStringAux, 0/*pPps->uiNumRefIdxL1Active - 1*/);
451
452
453 BsWriteOneBit (pLocalBitStringAux, false/*pPps->bWeightedPredFlag*/);
454 BsWriteBits (pLocalBitStringAux, 2, 0/*pPps->uiWeightedBiPredIdc*/);
455
456 BsWriteSE (pLocalBitStringAux, pPps->iPicInitQp - 26);
457 BsWriteSE (pLocalBitStringAux, pPps->iPicInitQs - 26);
458
459 BsWriteSE (pLocalBitStringAux, pPps->uiChromaQpIndexOffset);
460 BsWriteOneBit (pLocalBitStringAux, pPps->bDeblockingFilterControlPresentFlag);
461 BsWriteOneBit (pLocalBitStringAux, false/*pPps->bConstainedIntraPredFlag*/);
462 BsWriteOneBit (pLocalBitStringAux, false/*pPps->bRedundantPicCntPresentFlag*/);
463
464 BsRbspTrailingBits (pLocalBitStringAux);
465
466 return 0;
467 }
468
WelsGetPaddingOffset(int32_t iActualWidth,int32_t iActualHeight,int32_t iWidth,int32_t iHeight,SCropOffset & pOffset)469 static inline bool WelsGetPaddingOffset (int32_t iActualWidth, int32_t iActualHeight, int32_t iWidth,
470 int32_t iHeight, SCropOffset& pOffset) {
471 if ((iWidth < iActualWidth) || (iHeight < iActualHeight))
472 return false;
473
474 // make actual size even
475 iActualWidth -= (iActualWidth & 1);
476 iActualHeight -= (iActualHeight & 1);
477
478 pOffset.iCropLeft = 0;
479 pOffset.iCropRight = (iWidth - iActualWidth) / 2;
480 pOffset.iCropTop = 0;
481 pOffset.iCropBottom = (iHeight - iActualHeight) / 2;
482
483 return (iWidth > iActualWidth) || (iHeight > iActualHeight);
484 }
WelsInitSps(SWelsSPS * pSps,SSpatialLayerConfig * pLayerParam,SSpatialLayerInternal * pLayerParamInternal,const uint32_t kuiIntraPeriod,const int32_t kiNumRefFrame,const uint32_t kuiSpsId,const bool kbEnableFrameCropping,bool bEnableRc,const int32_t kiDlayerCount,bool bSVCBaselayer)485 int32_t WelsInitSps (SWelsSPS* pSps, SSpatialLayerConfig* pLayerParam, SSpatialLayerInternal* pLayerParamInternal,
486 const uint32_t kuiIntraPeriod, const int32_t kiNumRefFrame,
487 const uint32_t kuiSpsId, const bool kbEnableFrameCropping, bool bEnableRc,
488 const int32_t kiDlayerCount, bool bSVCBaselayer) {
489 memset (pSps, 0, sizeof (SWelsSPS));
490 pSps->uiSpsId = kuiSpsId;
491 pSps->iMbWidth = (pLayerParam->iVideoWidth + 15) >> 4;
492 pSps->iMbHeight = (pLayerParam->iVideoHeight + 15) >> 4;
493
494 //max value of both iFrameNum and POC are 2^16-1, in our encoder, iPOC=2*iFrameNum, so max of iFrameNum should be 2^15-1.--
495 pSps->uiLog2MaxFrameNum = 15;//16;
496 pSps->iLog2MaxPocLsb = 1 + pSps->uiLog2MaxFrameNum;
497
498 pSps->iNumRefFrames = kiNumRefFrame; /* min pRef size when fifo pRef operation*/
499
500 if (kbEnableFrameCropping) {
501 // TODO: get frame_crop_left_offset, frame_crop_right_offset, frame_crop_top_offset, frame_crop_bottom_offset
502 pSps->bFrameCroppingFlag = WelsGetPaddingOffset (pLayerParamInternal->iActualWidth, pLayerParamInternal->iActualHeight,
503 pLayerParam->iVideoWidth, pLayerParam->iVideoHeight, pSps->sFrameCrop);
504 } else {
505 pSps->bFrameCroppingFlag = false;
506 }
507 pSps->uiProfileIdc = pLayerParam->uiProfileIdc ? pLayerParam->uiProfileIdc : PRO_BASELINE;
508 if (pLayerParam->uiProfileIdc == PRO_BASELINE) {
509 pSps->bConstraintSet0Flag = true;
510 }
511 if (pLayerParam->uiProfileIdc <= PRO_MAIN) {
512 pSps->bConstraintSet1Flag = true;
513 }
514 if ((kiDlayerCount > 1) && bSVCBaselayer) {
515 pSps->bConstraintSet2Flag = true;
516 }
517
518 ELevelIdc uiLevel = WelsGetLevelIdc (pSps, pLayerParamInternal->fOutputFrameRate, pLayerParam->iSpatialBitrate);
519 //update level
520 //for Scalable Baseline, Scalable High, and Scalable High Intra profiles.If level_idc is equal to 9, the indicated level is level 1b.
521 //for the Baseline, Constrained Baseline, Main, and Extended profiles,If level_idc is equal to 11 and constraint_set3_flag is equal to 1, the indicated level is level 1b.
522 if ((uiLevel == LEVEL_1_B) &&
523 ((pSps->uiProfileIdc == PRO_BASELINE) || (pSps->uiProfileIdc == PRO_MAIN) || (pSps->uiProfileIdc == PRO_EXTENDED))) {
524 uiLevel = LEVEL_1_1;
525 pSps->bConstraintSet3Flag = true;
526 }
527 if ((pLayerParam->uiLevelIdc == LEVEL_UNKNOWN) || (pLayerParam->uiLevelIdc < uiLevel)) {
528 pLayerParam->uiLevelIdc = uiLevel;
529 }
530 pSps->iLevelIdc = pLayerParam->uiLevelIdc;
531
532 //bGapsInFrameNumValueAllowedFlag is false when only spatial layer number and temporal layer number is 1, and ltr is 0.
533 if ((kiDlayerCount == 1) && (pSps->iNumRefFrames == 1))
534 pSps->bGapsInFrameNumValueAllowedFlag = false;
535 else
536 pSps->bGapsInFrameNumValueAllowedFlag = true;
537
538 pSps->bVuiParamPresentFlag = true;
539
540 pSps->bAspectRatioPresent = pLayerParam->bAspectRatioPresent;
541 pSps->eAspectRatio = pLayerParam->eAspectRatio;
542 pSps->sAspectRatioExtWidth = pLayerParam->sAspectRatioExtWidth;
543 pSps->sAspectRatioExtHeight = pLayerParam->sAspectRatioExtHeight;
544
545 // See codec_app_def.h and parameter_sets.h for more info about members bVideoSignalTypePresent through uiColorMatrix.
546 pSps->bVideoSignalTypePresent = pLayerParam->bVideoSignalTypePresent;
547 pSps->uiVideoFormat = pLayerParam->uiVideoFormat;
548 pSps->bFullRange = pLayerParam->bFullRange;
549 pSps->bColorDescriptionPresent = pLayerParam->bColorDescriptionPresent;
550 pSps->uiColorPrimaries = pLayerParam->uiColorPrimaries;
551 pSps->uiTransferCharacteristics = pLayerParam->uiTransferCharacteristics;
552 pSps->uiColorMatrix = pLayerParam->uiColorMatrix;
553
554 return 0;
555 }
556
557
WelsInitSubsetSps(SSubsetSps * pSubsetSps,SSpatialLayerConfig * pLayerParam,SSpatialLayerInternal * pLayerParamInternal,const uint32_t kuiIntraPeriod,const int32_t kiNumRefFrame,const uint32_t kuiSpsId,const bool kbEnableFrameCropping,bool bEnableRc,const int32_t kiDlayerCount)558 int32_t WelsInitSubsetSps (SSubsetSps* pSubsetSps, SSpatialLayerConfig* pLayerParam,
559 SSpatialLayerInternal* pLayerParamInternal,
560 const uint32_t kuiIntraPeriod, const int32_t kiNumRefFrame,
561 const uint32_t kuiSpsId, const bool kbEnableFrameCropping, bool bEnableRc,
562 const int32_t kiDlayerCount) {
563 SWelsSPS* pSps = &pSubsetSps->pSps;
564
565 memset (pSubsetSps, 0, sizeof (SSubsetSps));
566
567 WelsInitSps (pSps, pLayerParam, pLayerParamInternal, kuiIntraPeriod, kiNumRefFrame, kuiSpsId, kbEnableFrameCropping,
568 bEnableRc, kiDlayerCount, false);
569
570 pSps->uiProfileIdc = pLayerParam->uiProfileIdc ;
571
572 pSubsetSps->sSpsSvcExt.iExtendedSpatialScalability = 0; /* ESS is 0 in default */
573 pSubsetSps->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag = false;
574 pSubsetSps->sSpsSvcExt.bSeqTcoeffLevelPredFlag = false;
575 pSubsetSps->sSpsSvcExt.bSliceHeaderRestrictionFlag = true;
576
577 return 0;
578 }
579
WelsInitPps(SWelsPPS * pPps,SWelsSPS * pSps,SSubsetSps * pSubsetSps,const uint32_t kuiPpsId,const bool kbDeblockingFilterPresentFlag,const bool kbUsingSubsetSps,const bool kbEntropyCodingModeFlag)580 int32_t WelsInitPps (SWelsPPS* pPps,
581 SWelsSPS* pSps,
582 SSubsetSps* pSubsetSps,
583 const uint32_t kuiPpsId,
584 const bool kbDeblockingFilterPresentFlag,
585 const bool kbUsingSubsetSps,
586 const bool kbEntropyCodingModeFlag) {
587 SWelsSPS* pUsedSps = NULL;
588 if (pPps == NULL || (pSps == NULL && pSubsetSps == NULL))
589 return 1;
590 if (!kbUsingSubsetSps) {
591 assert (pSps != NULL);
592 if (NULL == pSps)
593 return 1;
594 pUsedSps = pSps;
595 } else {
596 assert (pSubsetSps != NULL);
597 if (NULL == pSubsetSps)
598 return 1;
599 pUsedSps = &pSubsetSps->pSps;
600 }
601
602 /* fill picture parameter set syntax */
603 pPps->iPpsId = kuiPpsId;
604 pPps->iSpsId = pUsedSps->uiSpsId;
605 pPps->bEntropyCodingModeFlag = kbEntropyCodingModeFlag;
606 #if !defined(DISABLE_FMO_FEATURE)
607 pPps->uiNumSliceGroups = 1; //param->qos_param.sliceGroupCount;
608 if (pPps->uiNumSliceGroups > 1) {
609 pPps->uiSliceGroupMapType = 0; //param->qos_param.sliceGroupType;
610 if (pPps->uiSliceGroupMapType == 0) {
611 uint32_t uiGroup = 0;
612 while (uiGroup < pPps->uiNumSliceGroups) {
613 pPps->uiRunLength[uiGroup] = 25;
614 ++ uiGroup;
615 }
616 } else if (pPps->uiSliceGroupMapType == 2) {
617 memset (&pPps->uiTopLeft[0], 0, MAX_SLICEGROUP_IDS * sizeof (pPps->uiTopLeft[0]));
618 memset (&pPps->uiBottomRight[0], 0, MAX_SLICEGROUP_IDS * sizeof (pPps->uiBottomRight[0]));
619 } else if (pPps->uiSliceGroupMapType >= 3 &&
620 pPps->uiSliceGroupMapType <= 5) {
621 pPps->bSliceGroupChangeDirectionFlag = false;
622 pPps->uiSliceGroupChangeRate = 0;
623 } else if (pPps->uiSliceGroupMapType == 6) {
624 pPps->uiPicSizeInMapUnits = 1;
625 memset (&pPps->uiSliceGroupId[0], 0, MAX_SLICEGROUP_IDS * sizeof (pPps->uiSliceGroupId[0]));
626 }
627 }
628 #endif//!DISABLE_FMO_FEATURE
629
630 pPps->iPicInitQp = 26;
631 pPps->iPicInitQs = 26;
632
633 pPps->uiChromaQpIndexOffset = 0;
634 pPps->bDeblockingFilterControlPresentFlag = kbDeblockingFilterPresentFlag;
635
636 return 0;
637 }
638 } // namespace WelsEnc
639