• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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