• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*!
2  * \copy
3  *     Copyright (c)  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 
33 // ref_list_mgr_svc.c
34 #include "ref_list_mgr_svc.h"
35 #include "utils.h"
36 #include "picture_handle.h"
37 namespace WelsEnc {
38 
39 #define STR_ROOM 1
40 /*
41 *   reset LTR marking , recovery ,feedback state to default
42 */
ResetLtrState(SLTRState * pLtr)43 void ResetLtrState (SLTRState* pLtr) {
44   pLtr->bReceivedT0LostFlag = false;
45   pLtr->iLastRecoverFrameNum = 0;
46   pLtr->iLastCorFrameNumDec = -1;
47   pLtr->iCurFrameNumInDec = -1;
48 
49   // LTR mark
50   pLtr->iLTRMarkMode = LTR_DIRECT_MARK;
51   pLtr->iLTRMarkSuccessNum = 0; //successful marked num
52   pLtr->bLTRMarkingFlag = false; //decide whether current frame marked as LTR
53   pLtr->bLTRMarkEnable = false; //when LTR is confirmed and the interval is no smaller than the marking period
54   pLtr->iCurLtrIdx = 0;
55   memset (&pLtr->iLastLtrIdx , 0 , sizeof (pLtr->iLastLtrIdx)) ;
56   pLtr->uiLtrMarkInterval = 0;
57 
58   // LTR mark feedback
59   pLtr->uiLtrMarkState = NO_LTR_MARKING_FEEDBACK ;
60   pLtr->iLtrMarkFbFrameNum = -1;
61 }
62 
63 /*
64  *  reset reference picture list
65  */
WelsResetRefList(sWelsEncCtx * pCtx)66 void WelsResetRefList (sWelsEncCtx* pCtx) {
67   SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
68   int32_t i;
69 
70   for (i = 0; i < MAX_SHORT_REF_COUNT + 1; i++)
71     pRefList->pShortRefList[i] = NULL;
72   for (i = 0; i < pCtx->pSvcParam->iLTRRefNum + 1; i++)
73     pRefList->pLongRefList[i] = NULL;
74   for (i = 0; i < pCtx->pSvcParam->iNumRefFrame + 1; i++)
75     pRefList->pRef[i]->SetUnref();
76 
77   pRefList->uiLongRefCount = 0;
78   pRefList->uiShortRefCount = 0;
79   pRefList->pNextBuffer = pRefList->pRef[0];
80 }
81 
DeleteLTRFromLongList(sWelsEncCtx * pCtx,int32_t iIdx)82 static inline void DeleteLTRFromLongList (sWelsEncCtx* pCtx, int32_t iIdx) {
83   SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
84   int32_t k ;
85 
86   for (k = iIdx; k < pRefList->uiLongRefCount - 1; k++) {
87     pRefList->pLongRefList[k] = pRefList->pLongRefList[k + 1];
88   }
89   pRefList->pLongRefList[k] = NULL;
90   pRefList->uiLongRefCount--;
91 
92 }
DeleteSTRFromShortList(sWelsEncCtx * pCtx,int32_t iIdx)93 static inline void DeleteSTRFromShortList (sWelsEncCtx* pCtx, int32_t iIdx) {
94   SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
95   int32_t k ;
96 
97   for (k = iIdx; k < pRefList->uiShortRefCount - 1; k++) {
98     pRefList->pShortRefList[k] = pRefList->pShortRefList[k + 1];
99   }
100   pRefList->pShortRefList[k] = NULL;
101   pRefList->uiShortRefCount--;
102 
103 }
DeleteNonSceneLTR(sWelsEncCtx * pCtx)104 static void DeleteNonSceneLTR (sWelsEncCtx* pCtx) {
105   SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
106   for (int32_t i = 0; i < pCtx->pSvcParam->iNumRefFrame; ++i) {
107     SPicture* pRef = pRefList->pLongRefList[i];
108     if (pRef != NULL &&  pRef->bUsedAsRef && pRef->bIsLongRef && (!pRef->bIsSceneLTR) &&
109         (pCtx->uiTemporalId < pRef->uiTemporalId || pCtx->bCurFrameMarkedAsSceneLtr)) {
110       //this is our strategy to Unref all non-sceneLTR when the the current frame is sceneLTR
111       pRef->SetUnref();
112       DeleteLTRFromLongList (pCtx, i);
113       i--;
114     }
115   }
116 }
117 
CompareFrameNum(int32_t iFrameNumA,int32_t iFrameNumB,int32_t iMaxFrameNumPlus1)118 static inline int32_t CompareFrameNum (int32_t iFrameNumA, int32_t iFrameNumB, int32_t iMaxFrameNumPlus1) {
119   int64_t iNumA, iNumB, iDiffAB, iDiffMin;
120   if (iFrameNumA > iMaxFrameNumPlus1 || iFrameNumB > iMaxFrameNumPlus1) {
121     return -2;
122   }
123 #define  WelsAbsDiffInt64(a,b) ( (a) > (b) )?( a - b ):( b - a )
124 
125   iDiffAB = WelsAbsDiffInt64 ((int64_t) (iFrameNumA), (int64_t) (iFrameNumB));
126 
127   iDiffMin = iDiffAB;
128   if (iDiffMin == 0) {
129     return FRAME_NUM_EQUAL;
130   }
131 
132   iNumA = WelsAbsDiffInt64 ((int64_t) (iFrameNumA + iMaxFrameNumPlus1), (int64_t) (iFrameNumB));
133   if (iNumA == 0) {
134     return FRAME_NUM_EQUAL;
135   } else if (iDiffMin > iNumA) {
136     return FRAME_NUM_BIGGER;
137   }
138 
139   iNumB = WelsAbsDiffInt64 ((int64_t) (iFrameNumB + iMaxFrameNumPlus1), (int64_t) (iFrameNumA));
140   if (iNumB == 0) {
141     return FRAME_NUM_EQUAL;
142   } else if (iDiffMin > iNumB) {
143     return FRAME_NUM_SMALLER;
144   }
145 
146   return (iFrameNumA > iFrameNumB) ? (FRAME_NUM_BIGGER) : (FRAME_NUM_SMALLER);
147 
148 }
149 /*
150 *   delete failed mark according LTR recovery pRequest
151 */
DeleteInvalidLTR(sWelsEncCtx * pCtx)152 static inline void DeleteInvalidLTR (sWelsEncCtx* pCtx) {
153   SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
154   SPicture** pLongRefList = pRefList->pLongRefList;
155   SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId];
156   int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum);
157   int32_t i;
158   SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
159   SLogContext* pLogCtx = & (pCtx->sLogCtx);
160 
161   for (i = 0; i < LONG_TERM_REF_NUM; i++) {
162     if (pLongRefList[i] != NULL) {
163       if (CompareFrameNum (pLongRefList[i]->iFrameNum , pLtr->iLastCorFrameNumDec, iMaxFrameNumPlus1) == FRAME_NUM_BIGGER
164           && (CompareFrameNum (pLongRefList[i]->iFrameNum , pLtr->iCurFrameNumInDec,
165                                iMaxFrameNumPlus1) & (FRAME_NUM_EQUAL | FRAME_NUM_SMALLER))) {
166         WelsLog (pLogCtx, WELS_LOG_WARNING, "LTR ,invalid LTR delete ,long_term_idx = %d , iFrameNum =%d ",
167                  pLongRefList[i]->iLongTermPicNum, pLongRefList[i]->iFrameNum);
168         pLongRefList[i]->SetUnref();
169         DeleteLTRFromLongList (pCtx, i);
170         pLtr->bLTRMarkEnable = true;
171         if (pRefList->uiLongRefCount == 0) {
172           pParamInternal->bEncCurFrmAsIdrFlag = true;
173         }
174       } else if (CompareFrameNum (pLongRefList[i]->iMarkFrameNum , pLtr->iLastCorFrameNumDec ,
175                                   iMaxFrameNumPlus1) == FRAME_NUM_BIGGER
176                  && (CompareFrameNum (pLongRefList[i]->iMarkFrameNum, pLtr->iCurFrameNumInDec ,
177                                       iMaxFrameNumPlus1) & (FRAME_NUM_EQUAL | FRAME_NUM_SMALLER))
178                  && pLtr->iLTRMarkMode == LTR_DELAY_MARK) {
179         WelsLog (pLogCtx, WELS_LOG_WARNING, "LTR ,iMarkFrameNum invalid LTR delete ,long_term_idx = %d , iFrameNum =%d ",
180                  pLongRefList[i]->iLongTermPicNum, pLongRefList[i]->iFrameNum);
181         pLongRefList[i]->SetUnref();
182         DeleteLTRFromLongList (pCtx, i);
183         pLtr->bLTRMarkEnable = true;
184         if (pRefList->uiLongRefCount == 0) {
185           pParamInternal->bEncCurFrmAsIdrFlag = true;
186         }
187       }
188     }
189   }
190 
191 }
192 /*
193 *   handle LTR Mark feedback message
194 */
HandleLTRMarkFeedback(sWelsEncCtx * pCtx)195 static inline void HandleLTRMarkFeedback (sWelsEncCtx* pCtx) {
196   SRefList* pRefList            = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
197   SPicture** pLongRefList       = pRefList->pLongRefList;
198   SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId];
199   SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
200   int32_t i, j;
201 
202   if (pLtr->uiLtrMarkState == LTR_MARKING_SUCCESS) {
203     WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
204              "pLtr->uiLtrMarkState = %d, pLtr.iCurLtrIdx = %d , pLtr->iLtrMarkFbFrameNum = %d ,pCtx->iFrameNum = %d ",
205              pLtr->uiLtrMarkState, pLtr->iCurLtrIdx, pLtr->iLtrMarkFbFrameNum, pParamInternal->iFrameNum);
206     for (i = 0; i < pRefList->uiLongRefCount; i++) {
207       if (pLongRefList[i]->iFrameNum == pLtr->iLtrMarkFbFrameNum && pLongRefList[i]->uiRecieveConfirmed != RECIEVE_SUCCESS) {
208 
209         pLongRefList[i]->uiRecieveConfirmed = RECIEVE_SUCCESS;
210         pCtx->pVaa->uiValidLongTermPicIdx = pLongRefList[i]->iLongTermPicNum;
211 
212         pLtr->iCurFrameNumInDec  =
213           pLtr->iLastRecoverFrameNum =
214             pLtr->iLastCorFrameNumDec = pLtr->iLtrMarkFbFrameNum;
215 
216         for (j = 0; j < pRefList->uiLongRefCount; j++) {
217           if (pLongRefList[j]->iLongTermPicNum != pLtr->iCurLtrIdx) {
218             pLongRefList[j]->SetUnref();
219             DeleteLTRFromLongList (pCtx, j);
220           }
221         }
222 
223         pLtr->iLTRMarkSuccessNum++;
224         pLtr->iCurLtrIdx = (pLtr->iCurLtrIdx + 1) % LONG_TERM_REF_NUM;
225         pLtr->iLTRMarkMode = (pLtr->iLTRMarkSuccessNum >= (LONG_TERM_REF_NUM)) ? (LTR_DELAY_MARK) : (LTR_DIRECT_MARK);
226         WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "LTR mark mode =%d", pLtr->iLTRMarkMode);
227         pLtr->bLTRMarkEnable = true;
228         break;
229       }
230     }
231     pLtr->uiLtrMarkState = NO_LTR_MARKING_FEEDBACK;
232   } else if (pLtr->uiLtrMarkState == LTR_MARKING_FAILED) {
233     for (i = 0; i < pRefList->uiLongRefCount; i++) {
234       if (pLongRefList[i]->iFrameNum == pLtr->iLtrMarkFbFrameNum) {
235         pLongRefList[i]->SetUnref();
236         DeleteLTRFromLongList (pCtx, i);
237         break;
238       }
239     }
240     pLtr->uiLtrMarkState = NO_LTR_MARKING_FEEDBACK;
241     pLtr->bLTRMarkEnable = true;
242 
243     if (pLtr->iLTRMarkSuccessNum == 0) {
244       pParamInternal->bEncCurFrmAsIdrFlag = true; // no LTR , means IDR recieve failed, force next frame IDR
245     }
246   }
247 }
248 /*
249  *  LTR mark process
250  */
LTRMarkProcess(sWelsEncCtx * pCtx)251 static inline void LTRMarkProcess (sWelsEncCtx* pCtx) {
252   SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
253   SPicture** pLongRefList = pRefList->pLongRefList;
254   SPicture** pShortRefList = pRefList->pShortRefList;
255   SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId];
256   int32_t iGoPFrameNumInterval = ((pCtx->pSvcParam->uiGopSize >> 1) > 1) ? (pCtx->pSvcParam->uiGopSize >> 1) : (1);
257   int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum);
258   int32_t i = 0;
259   int32_t j = 0;
260   bool bMoveLtrFromShortToLong = false;
261   SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
262 
263   if (pCtx->eSliceType == I_SLICE) {
264     i = 0;
265     pShortRefList[i]->uiRecieveConfirmed = RECIEVE_SUCCESS;
266   } else if (pLtr->bLTRMarkingFlag) {
267     pCtx->pVaa->uiMarkLongTermPicIdx = pLtr->iCurLtrIdx;
268 
269     if (pLtr->iLTRMarkMode == LTR_DELAY_MARK) {
270       for (i = 0; i < pRefList->uiShortRefCount; i++) {
271         if (CompareFrameNum (pParamInternal->iFrameNum, pShortRefList[i]->iFrameNum + iGoPFrameNumInterval,
272                              iMaxFrameNumPlus1) == FRAME_NUM_EQUAL) {
273           break;
274         }
275       }
276     }
277   }
278 
279   if (pCtx->eSliceType == I_SLICE || pLtr->bLTRMarkingFlag) {
280     pShortRefList[i]->bIsLongRef = true;
281     pShortRefList[i]->iLongTermPicNum = pLtr->iCurLtrIdx;
282     pShortRefList[i]->iMarkFrameNum = pParamInternal->iFrameNum;
283   }
284 
285   // delay one gop to move LTR from int16_t list to int32_t list
286   if (pLtr->iLTRMarkMode == LTR_DIRECT_MARK && pCtx->eSliceType != I_SLICE && !pLtr->bLTRMarkingFlag) {
287     for (j = 0; j < pRefList->uiShortRefCount; j++) {
288       if (pRefList->pShortRefList[j]->bIsLongRef) {
289         i = j;
290         bMoveLtrFromShortToLong = true;
291         break;
292       }
293     }
294   }
295 
296   if ((pLtr->iLTRMarkMode == LTR_DELAY_MARK && pLtr->bLTRMarkingFlag)
297       || ((pLtr->iLTRMarkMode == LTR_DIRECT_MARK) && (bMoveLtrFromShortToLong))) {
298     pCtx->bRefOfCurTidIsLtr[pCtx->uiDependencyId][pCtx->uiTemporalId] = true;
299 
300     if (pRefList->uiLongRefCount > 0) {
301       memmove (&pRefList->pLongRefList[1], &pRefList->pLongRefList[0],
302                pRefList->uiLongRefCount * sizeof (SPicture*)); // confirmed_safe_unsafe_usage
303     }
304     pLongRefList[0] = pShortRefList[i];
305     pRefList->uiLongRefCount++;
306     if (pRefList->uiLongRefCount > pCtx->pSvcParam->iLTRRefNum) {
307       pRefList->pLongRefList[pRefList->uiLongRefCount - 1]->SetUnref();
308       DeleteLTRFromLongList (pCtx, pRefList->uiLongRefCount - 1);
309     }
310     DeleteSTRFromShortList (pCtx, i);
311   }
312 }
313 
LTRMarkProcessScreen(sWelsEncCtx * pCtx)314 static inline void LTRMarkProcessScreen (sWelsEncCtx* pCtx) {
315   SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
316   SPicture** pLongRefList = pRefList->pLongRefList;
317   int32_t iLtrIdx =  pCtx->pDecPic->iLongTermPicNum;
318   pCtx->pVaa->uiMarkLongTermPicIdx = pCtx->pDecPic->iLongTermPicNum;
319 
320   assert (CheckInRangeCloseOpen (iLtrIdx, 0, MAX_REF_PIC_COUNT));
321   if (pLongRefList[iLtrIdx] != NULL) {
322     pLongRefList[iLtrIdx]->SetUnref();
323   } else {
324     pRefList->uiLongRefCount++;
325   }
326   pLongRefList[iLtrIdx] = pCtx->pDecPic;
327 }
328 
PrefetchNextBuffer(sWelsEncCtx * pCtx)329 static void PrefetchNextBuffer (sWelsEncCtx* pCtx) {
330   SRefList* pRefList            = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
331   const int32_t kiNumRef        = pCtx->pSvcParam->iNumRefFrame;
332   int32_t i;
333 
334   pRefList->pNextBuffer = NULL;
335   for (i = 0; i < kiNumRef + 1; i++) {
336     if (!pRefList->pRef[i]->bUsedAsRef) {
337       pRefList->pNextBuffer = pRefList->pRef[i];
338       break;
339     }
340   }
341 
342   if (pRefList->pNextBuffer == NULL && pRefList->uiShortRefCount > 0) {
343     pRefList->pNextBuffer = pRefList->pShortRefList[pRefList->uiShortRefCount - 1];
344     pRefList->pNextBuffer->SetUnref();
345   }
346 
347   pCtx->pDecPic = pRefList->pNextBuffer;
348 }
349 
350 /*
351  *  update reference picture list
352  */
WelsUpdateRefList(sWelsEncCtx * pCtx)353 bool WelsUpdateRefList (sWelsEncCtx* pCtx) {
354   SRefList* pRefList                = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
355   SLTRState* pLtr                   = &pCtx->pLtr[pCtx->uiDependencyId];
356   SSpatialLayerInternal* pParamD    = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
357 
358   int32_t iRefIdx                   = 0;
359   const uint8_t kuiTid              = pCtx->uiTemporalId;
360   const uint8_t kuiDid              = pCtx->uiDependencyId;
361   const EWelsSliceType keSliceType  = pCtx->eSliceType;
362   uint32_t i = 0;
363   // Need update pRef list in case store base layer or target dependency layer construction
364   if (NULL == pCtx->pCurDqLayer)
365     return false;
366 
367   if (NULL == pRefList || NULL == pRefList->pRef[0])
368     return false;
369 
370   if (NULL != pCtx->pDecPic) {
371 #if !defined(ENABLE_FRAME_DUMP) // to save complexity, 1/6/2009
372     if ((pParamD->iHighestTemporalId == 0) || (kuiTid < pParamD->iHighestTemporalId))
373 #endif// !ENABLE_FRAME_DUMP
374       // Expanding picture for future reference
375       ExpandReferencingPicture (pCtx->pDecPic->pData, pCtx->pDecPic->iWidthInPixel, pCtx->pDecPic->iHeightInPixel,
376                                 pCtx->pDecPic->iLineSize,
377                                 pCtx->pFuncList->sExpandPicFunc.pfExpandLumaPicture, pCtx->pFuncList->sExpandPicFunc.pfExpandChromaPicture);
378 
379     // move picture in list
380     pCtx->pDecPic->uiTemporalId = kuiTid;
381     pCtx->pDecPic->uiSpatialId  = kuiDid;
382     pCtx->pDecPic->iFrameNum    = pParamD->iFrameNum;
383     pCtx->pDecPic->iFramePoc    = pParamD->iPOC;
384     pCtx->pDecPic->uiRecieveConfirmed = RECIEVE_UNKOWN;
385     pCtx->pDecPic->bUsedAsRef   = true;
386 
387     for (iRefIdx = pRefList->uiShortRefCount - 1; iRefIdx >= 0; --iRefIdx) {
388       pRefList->pShortRefList[iRefIdx + 1] = pRefList->pShortRefList[iRefIdx];
389     }
390     pRefList->pShortRefList[0] = pCtx->pDecPic;
391     pRefList->uiShortRefCount++;
392   }
393 
394   if (keSliceType == P_SLICE) {
395     if (pCtx->uiTemporalId == 0) {
396       if (pCtx->pSvcParam->bEnableLongTermReference) {
397         LTRMarkProcess (pCtx);
398         DeleteInvalidLTR (pCtx);
399         HandleLTRMarkFeedback (pCtx);
400 
401         pLtr->bReceivedT0LostFlag = false; // reset to false due to the recovery is finished
402         pLtr->bLTRMarkingFlag = false;
403         ++pLtr->uiLtrMarkInterval;
404       }
405 
406       for (i = pRefList->uiShortRefCount - 1; i > 0; i--) {
407         pRefList->pShortRefList[i]->SetUnref();
408         DeleteSTRFromShortList (pCtx, i);
409       }
410       if (pRefList->uiShortRefCount > 0 && (pRefList->pShortRefList[0]->uiTemporalId > 0
411                                             || pRefList->pShortRefList[0]->iFrameNum != pParamD->iFrameNum)) {
412         pRefList->pShortRefList[0]->SetUnref();
413         DeleteSTRFromShortList (pCtx, 0);
414       }
415     }
416   } else { // in case IDR currently coding
417     if (pCtx->pSvcParam->bEnableLongTermReference) {
418       LTRMarkProcess (pCtx);
419 
420       pLtr->iCurLtrIdx = (pLtr->iCurLtrIdx + 1) % LONG_TERM_REF_NUM;
421       pLtr->iLTRMarkSuccessNum = 1; //IDR default suceess
422       pLtr->bLTRMarkEnable =  true;
423       pLtr->uiLtrMarkInterval = 0;
424 
425       pCtx->pVaa->uiValidLongTermPicIdx = 0;
426       pCtx->pVaa->uiMarkLongTermPicIdx = 0;
427     }
428   }
429   pCtx->pReferenceStrategy->EndofUpdateRefList();
430   return true;
431 }
432 
CheckCurMarkFrameNumUsed(sWelsEncCtx * pCtx)433 bool CheckCurMarkFrameNumUsed (sWelsEncCtx* pCtx) {
434   SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId];
435   SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
436   SPicture** pLongRefList = pRefList->pLongRefList;
437   int32_t iGoPFrameNumInterval = ((pCtx->pSvcParam->uiGopSize >> 1) > 1) ? (pCtx->pSvcParam->uiGopSize >> 1) : (1);
438   int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum);
439   SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
440   int32_t i;
441 
442   for (i = 0; i < pRefList->uiLongRefCount; i++) {
443     if ((pParamInternal->iFrameNum == pLongRefList[i]->iFrameNum && pLtr->iLTRMarkMode == LTR_DIRECT_MARK) ||
444         (CompareFrameNum (pParamInternal->iFrameNum + iGoPFrameNumInterval, pLongRefList[i]->iFrameNum,
445                           iMaxFrameNumPlus1) == FRAME_NUM_EQUAL  && pLtr->iLTRMarkMode == LTR_DELAY_MARK)) {
446       return false;
447     }
448   }
449 
450   return true;
451 }
452 
WelsMarkMMCORefInfoWithBase(SSlice ** ppSliceList,SSlice * pBaseSlice,const int32_t kiCountSliceNum)453 static inline void WelsMarkMMCORefInfoWithBase (SSlice** ppSliceList,
454     SSlice* pBaseSlice,
455     const int32_t kiCountSliceNum) {
456   int32_t iSliceIdx = 0;
457   SSliceHeaderExt* pSliceHdrExt = NULL;
458   SSliceHeaderExt* pBaseSHExt   = &pBaseSlice->sSliceHeaderExt;
459 
460   for (iSliceIdx = 0; iSliceIdx < kiCountSliceNum; iSliceIdx++) {
461     pSliceHdrExt = &ppSliceList[iSliceIdx]->sSliceHeaderExt;
462     memcpy (&pSliceHdrExt->sSliceHeader.sRefMarking, &pBaseSHExt->sSliceHeader.sRefMarking, sizeof (SRefPicMarking));
463   }
464 }
465 
WelsMarkMMCORefInfo(sWelsEncCtx * pCtx,SLTRState * pLtr,SSlice ** ppSliceList,const int32_t kiCountSliceNum)466 void WelsMarkMMCORefInfo (sWelsEncCtx* pCtx, SLTRState* pLtr,
467                           SSlice** ppSliceList, const int32_t kiCountSliceNum) {
468   SSlice* pBaseSlice            = ppSliceList[0];
469   SRefPicMarking* pRefPicMark   = &pBaseSlice->sSliceHeaderExt.sSliceHeader.sRefMarking;
470   int32_t iGoPFrameNumInterval  = ((pCtx->pSvcParam->uiGopSize >> 1) > 1) ? (pCtx->pSvcParam->uiGopSize >> 1) : (1);
471 
472   memset (pRefPicMark, 0, sizeof (SRefPicMarking));
473 
474   if (pCtx->pSvcParam->bEnableLongTermReference && pLtr->bLTRMarkingFlag) {
475     if (pLtr->iLTRMarkMode == LTR_DIRECT_MARK) {
476       pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount].iMaxLongTermFrameIdx = LONG_TERM_REF_NUM - 1;
477       pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount++].iMmcoType = MMCO_SET_MAX_LONG;
478 
479       pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount].iDiffOfPicNum = iGoPFrameNumInterval;
480       pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount++].iMmcoType = MMCO_SHORT2UNUSED;
481 
482       pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount].iLongTermFrameIdx = pLtr->iCurLtrIdx;
483       pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount++].iMmcoType = MMCO_LONG;
484     } else if (pLtr->iLTRMarkMode == LTR_DELAY_MARK) {
485       pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount].iDiffOfPicNum = iGoPFrameNumInterval;
486       pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount].iLongTermFrameIdx = pLtr->iCurLtrIdx;
487       pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount++].iMmcoType = MMCO_SHORT2LONG;
488     }
489   }
490 
491   WelsMarkMMCORefInfoWithBase (ppSliceList, pBaseSlice, kiCountSliceNum);
492 }
493 
WelsMarkPic(sWelsEncCtx * pCtx)494 void WelsMarkPic (sWelsEncCtx* pCtx) {
495   SLTRState* pLtr               = &pCtx->pLtr[pCtx->uiDependencyId];
496   const int32_t kiCountSliceNum = pCtx->pCurDqLayer->iMaxSliceNum;
497 
498   if (pCtx->pSvcParam->bEnableLongTermReference && pLtr->bLTRMarkEnable && pCtx->uiTemporalId == 0) {
499     if (!pLtr->bReceivedT0LostFlag && pLtr->uiLtrMarkInterval > pCtx->pSvcParam->iLtrMarkPeriod
500         && CheckCurMarkFrameNumUsed (pCtx)) {
501       pLtr->bLTRMarkingFlag = true;
502       pLtr->bLTRMarkEnable = false;
503       pLtr->uiLtrMarkInterval = 0;
504       for (int32_t i = 0 ; i < MAX_TEMPORAL_LAYER_NUM; ++i) {
505         if (pCtx->uiTemporalId < i || pCtx->uiTemporalId == 0) {
506           pLtr->iLastLtrIdx[i] = pLtr->iCurLtrIdx;
507         }
508       }
509     } else {
510       pLtr->bLTRMarkingFlag = false;
511     }
512   }
513 
514   WelsMarkMMCORefInfo (pCtx, pLtr, pCtx->pCurDqLayer->ppSliceInLayer, kiCountSliceNum);
515 }
516 
FilterLTRRecoveryRequest(sWelsEncCtx * pCtx,SLTRRecoverRequest * pLTRRecoverRequest)517 int32_t FilterLTRRecoveryRequest (sWelsEncCtx* pCtx, SLTRRecoverRequest* pLTRRecoverRequest) {
518   //if disable LTR, force IDR
519   if (!pCtx->pSvcParam->bEnableLongTermReference) {
520     for (int32_t iDid = 0; iDid < pCtx->pSvcParam->iSpatialLayerNum; iDid++) {
521       SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[iDid];
522       pParamInternal->bEncCurFrmAsIdrFlag = true;
523     }
524   } else {
525     SLTRRecoverRequest* pRequest = pLTRRecoverRequest;
526     int32_t iLayerId = pLTRRecoverRequest->iLayerId;
527     if ((iLayerId < 0) || (iLayerId >= pCtx->pSvcParam->iSpatialLayerNum))
528       return false;
529 
530     SLTRState* pLtr = &pCtx->pLtr[iLayerId];
531     int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum);
532     SSpatialLayerInternal* pParamInternal    = &pCtx->pSvcParam->sDependencyLayers[iLayerId];
533     if (pRequest->uiFeedbackType == LTR_RECOVERY_REQUEST &&  pRequest->uiIDRPicId == pParamInternal->uiIdrPicId) {
534       if (pRequest->iLastCorrectFrameNum == -1) {
535         pParamInternal->bEncCurFrmAsIdrFlag = true;
536         return true;
537       } else if (pRequest->iCurrentFrameNum == -1) {
538         pLtr->bReceivedT0LostFlag = true;
539         return true;
540       } else if ((CompareFrameNum (pLtr->iLastRecoverFrameNum , pRequest->iLastCorrectFrameNum,
541                                    iMaxFrameNumPlus1) & (FRAME_NUM_EQUAL | FRAME_NUM_SMALLER)) // t0 lost
542                  || ((CompareFrameNum (pLtr->iLastRecoverFrameNum , pRequest->iCurrentFrameNum,
543                                        iMaxFrameNumPlus1) & (FRAME_NUM_EQUAL | FRAME_NUM_SMALLER)) &&
544                      CompareFrameNum (pLtr->iLastRecoverFrameNum , pRequest->iLastCorrectFrameNum,
545                                       iMaxFrameNumPlus1) == FRAME_NUM_BIGGER)) { // recovery failed
546 
547         pLtr->bReceivedT0LostFlag = true;
548         pLtr->iLastCorFrameNumDec = pRequest->iLastCorrectFrameNum;
549         pLtr->iCurFrameNumInDec = pRequest->iCurrentFrameNum;
550         WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
551                  "Receive valid LTR recovery pRequest,feedback_type = %d ,uiIdrPicId = %d , current_frame_num = %d , last correct frame num = %d"
552                  , pRequest->uiFeedbackType, pRequest->uiIDRPicId, pRequest->iCurrentFrameNum, pRequest->iLastCorrectFrameNum);
553       }
554 
555       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
556                "Receive LTR recovery pRequest,feedback_type = %d ,uiIdrPicId = %d , current_frame_num = %d , last correct frame num = %d"
557                , pRequest->uiFeedbackType, pRequest->uiIDRPicId, pRequest->iCurrentFrameNum, pRequest->iLastCorrectFrameNum);
558     }
559   }
560 
561   return true;
562 }
FilterLTRMarkingFeedback(sWelsEncCtx * pCtx,SLTRMarkingFeedback * pLTRMarkingFeedback)563 void FilterLTRMarkingFeedback (sWelsEncCtx* pCtx, SLTRMarkingFeedback* pLTRMarkingFeedback) {
564   int32_t iLayerId = pLTRMarkingFeedback->iLayerId;
565   if ((iLayerId < 0) || (iLayerId >= pCtx->pSvcParam->iSpatialLayerNum)) {
566     return;
567   }
568   SLTRState* pLtr = &pCtx->pLtr[iLayerId];
569   assert (pLTRMarkingFeedback);
570   if (pCtx->pSvcParam->bEnableLongTermReference) {
571     SSpatialLayerInternal* pParamInternal    = &pCtx->pSvcParam->sDependencyLayers[iLayerId];
572     if (pLTRMarkingFeedback->uiIDRPicId == pParamInternal->uiIdrPicId
573         && (pLTRMarkingFeedback->uiFeedbackType == LTR_MARKING_SUCCESS
574             || pLTRMarkingFeedback->uiFeedbackType == LTR_MARKING_FAILED)) { // avoid error pData
575       pLtr->uiLtrMarkState = pLTRMarkingFeedback->uiFeedbackType;
576       pLtr->iLtrMarkFbFrameNum =  pLTRMarkingFeedback->iLTRFrameNum ;
577       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
578                "Receive valid LTR marking feedback, feedback_type = %d , uiIdrPicId = %d , LTR_frame_num = %d , cur_idr_pic_id = %d",
579                pLTRMarkingFeedback->uiFeedbackType, pLTRMarkingFeedback->uiIDRPicId, pLTRMarkingFeedback->iLTRFrameNum ,
580                pParamInternal->uiIdrPicId);
581 
582     } else {
583       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
584                "Receive LTR marking feedback, feedback_type = %d , uiIdrPicId = %d , LTR_frame_num = %d , cur_idr_pic_id = %d",
585                pLTRMarkingFeedback->uiFeedbackType, pLTRMarkingFeedback->uiIDRPicId, pLTRMarkingFeedback->iLTRFrameNum ,
586                pParamInternal->uiIdrPicId);
587     }
588   }
589 }
590 
591 /*
592  *  build reference picture list
593  */
WelsBuildRefList(sWelsEncCtx * pCtx,const int32_t iPOC,int32_t iBestLtrRefIdx)594 bool WelsBuildRefList (sWelsEncCtx* pCtx, const int32_t iPOC, int32_t iBestLtrRefIdx) {
595   SRefList* pRefList            = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
596   SLTRState* pLtr               = &pCtx->pLtr[pCtx->uiDependencyId];
597   const int32_t kiNumRef        = pCtx->pSvcParam->iNumRefFrame;
598   const uint8_t kuiTid          = pCtx->uiTemporalId;
599   uint32_t i                    = 0;
600   SSpatialLayerInternal* pParamD    = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
601   // to support any type of cur_dq->mgs_control
602   //    [ 0:    using current layer to do ME/MC;
603   //     -1:    using store base layer to do ME/MC;
604   //      2:    using highest layer to do ME/MC; ]
605 
606   // build reference list 0/1 if applicable
607 
608   pCtx->iNumRef0 = 0;
609   if (pCtx->eSliceType != I_SLICE) {
610     if (pCtx->pSvcParam->bEnableLongTermReference && pLtr->bReceivedT0LostFlag && pCtx->uiTemporalId == 0) {
611       for (i = 0; i < pRefList->uiLongRefCount; i++) {
612         if (pRefList->pLongRefList[i]->uiRecieveConfirmed == RECIEVE_SUCCESS) {
613           pCtx->pCurDqLayer->pRefOri[pCtx->iNumRef0] = pRefList->pLongRefList[i];
614           pCtx->pRefList0[pCtx->iNumRef0++] = pRefList->pLongRefList[i];
615           pLtr->iLastRecoverFrameNum = pParamD->iFrameNum;
616           WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
617                    "pRef is int32_t !iLastRecoverFrameNum = %d, pRef iFrameNum = %d,LTR number = %d,",
618                    pLtr->iLastRecoverFrameNum, pCtx->pRefList0[0]->iFrameNum, pRefList->uiLongRefCount);
619           break;
620         }
621       }
622     } else {
623       for (i = 0; i < pRefList->uiShortRefCount; ++ i) {
624         SPicture* pRef = pRefList->pShortRefList[i];
625         if (pRef != NULL && pRef->bUsedAsRef && pRef->iFramePoc >= 0 && pRef->uiTemporalId <= kuiTid) {
626           pCtx->pCurDqLayer->pRefOri[pCtx->iNumRef0] = pRef;
627           pCtx->pRefList0[pCtx->iNumRef0++] = pRef;
628           WelsLog (& (pCtx->sLogCtx), WELS_LOG_DETAIL,
629                    "WelsBuildRefList pCtx->uiTemporalId = %d,pRef->iFrameNum = %d,pRef->uiTemporalId = %d",
630                    pCtx->uiTemporalId, pRef->iFrameNum, pRef->uiTemporalId);
631         }
632       }
633     }
634   } else { // safe for IDR
635     WelsResetRefList (pCtx);  //for IDR, SHOULD reset pRef list.
636     ResetLtrState (&pCtx->pLtr[pCtx->uiDependencyId]); //SHOULD update it when IDR.
637     for (int32_t k = 0; k < MAX_TEMPORAL_LEVEL; k++) {
638       pCtx->bRefOfCurTidIsLtr[pCtx->uiDependencyId][k] = false;
639     }
640     pCtx->pRefList0[0] = NULL;
641   }
642 
643   if (pCtx->iNumRef0 > kiNumRef)
644     pCtx->iNumRef0 = kiNumRef;
645   return (pCtx->iNumRef0 > 0 || pCtx->eSliceType == I_SLICE) ? (true) : (false);
646 }
647 
UpdateBlockStatic(sWelsEncCtx * pCtx)648 static void UpdateBlockStatic (sWelsEncCtx* pCtx) {
649   SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa);
650   assert (pCtx->iNumRef0 == 1); //multi-ref is not support yet?
651   for (int32_t idx = 0; idx < pCtx->iNumRef0; idx++) {
652     //TODO: we need to re-factor the source picture storage first,
653     //and then use original frame of the ref to do this calculation for better vaa algo implementation
654     SPicture* pRef = pCtx->pRefList0[idx];
655     if (pVaaExt->iVaaBestRefFrameNum != pRef->iFrameNum) {
656       //re-do the calculation
657       pCtx->pVpp->UpdateBlockIdcForScreen (pVaaExt->pVaaBestBlockStaticIdc, pRef, pCtx->pEncPic);
658     }
659   }
660 }
661 
WelsUpdateSliceHeaderSyntax(sWelsEncCtx * pCtx,const int32_t iAbsDiffPicNumMinus1,SSlice ** ppSliceList,const int32_t uiFrameType)662 void WelsUpdateSliceHeaderSyntax (sWelsEncCtx* pCtx,  const int32_t iAbsDiffPicNumMinus1,
663                                   SSlice** ppSliceList, const int32_t uiFrameType) {
664   const int32_t kiCountSliceNum = pCtx->pCurDqLayer->iMaxSliceNum;
665   SLTRState* pLtr               = &pCtx->pLtr[pCtx->uiDependencyId];
666   int32_t iIdx = 0;
667 
668   assert (kiCountSliceNum > 0);
669 
670   for (iIdx = 0; iIdx < kiCountSliceNum; iIdx++) {
671     SSliceHeaderExt*    pSliceHdrExt = &ppSliceList[iIdx]->sSliceHeaderExt;
672     SSliceHeader*       pSliceHdr = &pSliceHdrExt->sSliceHeader;
673     SRefPicListReorderSyntax* pRefReorder = &pSliceHdr->sRefReordering;
674     SRefPicMarking* pRefPicMark = &pSliceHdr->sRefMarking;
675 
676     /*syntax for num_ref_idx_l0_active_minus1*/
677     pSliceHdr->uiRefCount = pCtx->iNumRef0;
678     if (pCtx->iNumRef0 > 0) {
679       if ((!pCtx->pRefList0[0]->bIsLongRef) || (!pCtx->pSvcParam->bEnableLongTermReference)) {
680         pRefReorder->SReorderingSyntax[0].uiReorderingOfPicNumsIdc = 0;
681         pRefReorder->SReorderingSyntax[0].uiAbsDiffPicNumMinus1 = iAbsDiffPicNumMinus1;
682         pRefReorder->SReorderingSyntax[1].uiReorderingOfPicNumsIdc = 3;
683       } else {
684         int32_t iRefIdx = 0;
685         for (iRefIdx = 0; iRefIdx < pCtx->iNumRef0; iRefIdx++) {
686           pRefReorder->SReorderingSyntax[iRefIdx].uiReorderingOfPicNumsIdc = 2;
687           pRefReorder->SReorderingSyntax[iRefIdx].iLongTermPicNum = pCtx->pRefList0[iRefIdx]->iLongTermPicNum;
688         }
689         pRefReorder->SReorderingSyntax[iRefIdx].uiReorderingOfPicNumsIdc = 3;
690       }
691     }
692 
693     /*syntax for dec_ref_pic_marking()*/
694     if (videoFrameTypeIDR == uiFrameType) {
695       pRefPicMark->bNoOutputOfPriorPicsFlag = false;
696       pRefPicMark->bLongTermRefFlag = pCtx->pSvcParam->bEnableLongTermReference;
697     } else {
698       if (pCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME)
699         pRefPicMark->bAdaptiveRefPicMarkingModeFlag = pCtx->pSvcParam->bEnableLongTermReference;
700       else
701         pRefPicMark->bAdaptiveRefPicMarkingModeFlag = (pCtx->pSvcParam->bEnableLongTermReference
702             && pLtr->bLTRMarkingFlag) ? (true) : (false);
703     }
704   }
705 }
706 
707 /*
708  *  update syntax for reference base related
709  */
WelsUpdateRefSyntax(sWelsEncCtx * pCtx,const int32_t iPOC,const int32_t uiFrameType)710 void WelsUpdateRefSyntax (sWelsEncCtx* pCtx, const int32_t iPOC, const int32_t uiFrameType) {
711   int32_t iAbsDiffPicNumMinus1   = -1;
712   SSpatialLayerInternal* pParamD    = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
713   /*syntax for ref_pic_list_reordering()*/
714   if (pCtx->iNumRef0 > 0) {
715     iAbsDiffPicNumMinus1 = pParamD->iFrameNum - (pCtx->pRefList0[0]->iFrameNum) - 1;
716 
717     if (iAbsDiffPicNumMinus1 < 0) {
718       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "WelsUpdateRefSyntax():::uiAbsDiffPicNumMinus1:%d", iAbsDiffPicNumMinus1);
719       iAbsDiffPicNumMinus1 += (1 << (pCtx->pSps->uiLog2MaxFrameNum));
720       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "WelsUpdateRefSyntax():::uiAbsDiffPicNumMinus1< 0, update as:%d",
721                iAbsDiffPicNumMinus1);
722     }
723   }
724 
725   WelsUpdateSliceHeaderSyntax (pCtx, iAbsDiffPicNumMinus1, pCtx->pCurDqLayer->ppSliceInLayer, uiFrameType);
726 }
727 
UpdateOriginalPicInfo(SPicture * pOrigPic,SPicture * pReconPic)728 static inline void UpdateOriginalPicInfo (SPicture* pOrigPic, SPicture* pReconPic) {
729   if (!pOrigPic)
730     return;
731 
732   pOrigPic->iPictureType = pReconPic->iPictureType;
733   pOrigPic->iFramePoc = pReconPic->iFramePoc;
734   pOrigPic->iFrameNum = pReconPic->iFrameNum;
735   pOrigPic->uiSpatialId = pReconPic->uiSpatialId;
736   pOrigPic->uiTemporalId = pReconPic->uiTemporalId;
737   pOrigPic->iLongTermPicNum = pReconPic->iLongTermPicNum;
738   pOrigPic->bUsedAsRef = pReconPic->bUsedAsRef;
739   pOrigPic->bIsLongRef = pReconPic->bIsLongRef;
740   pOrigPic->bIsSceneLTR = pReconPic->bIsSceneLTR;
741   pOrigPic->iFrameAverageQp = pReconPic->iFrameAverageQp;
742 }
743 
UpdateSrcPicListLosslessScreenRefSelectionWithLtr(sWelsEncCtx * pCtx)744 static void UpdateSrcPicListLosslessScreenRefSelectionWithLtr (sWelsEncCtx* pCtx) {
745   int32_t iDIdx = pCtx->uiDependencyId;
746   //update info in src list
747   UpdateOriginalPicInfo (pCtx->pEncPic, pCtx->pDecPic);
748   PrefetchNextBuffer (pCtx);
749   pCtx->pVpp->UpdateSrcListLosslessScreenRefSelectionWithLtr (pCtx->pEncPic, iDIdx,  pCtx->pVaa->uiMarkLongTermPicIdx,
750       pCtx->ppRefPicListExt[iDIdx]->pLongRefList);
751 }
752 
UpdateSrcPicList(sWelsEncCtx * pCtx)753 static void UpdateSrcPicList (sWelsEncCtx* pCtx) {
754   int32_t iDIdx = pCtx->uiDependencyId;
755   //update info in src list
756   UpdateOriginalPicInfo (pCtx->pEncPic, pCtx->pDecPic);
757   PrefetchNextBuffer (pCtx);
758   pCtx->pVpp->UpdateSrcList (pCtx->pEncPic, iDIdx, pCtx->ppRefPicListExt[iDIdx]->pShortRefList,
759                              pCtx->ppRefPicListExt[iDIdx]->uiShortRefCount);
760 }
761 
WelsUpdateRefListScreen(sWelsEncCtx * pCtx)762 bool WelsUpdateRefListScreen (sWelsEncCtx* pCtx) {
763   SRefList* pRefList                = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
764   SLTRState* pLtr                   = &pCtx->pLtr[pCtx->uiDependencyId];
765   SSpatialLayerInternal* pParamD    = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
766   const uint8_t kuiTid              = pCtx->uiTemporalId;
767   // Need update ref list in case store base layer or target dependency layer construction
768   if (NULL == pCtx->pCurDqLayer)
769     return false;
770 
771   if (NULL == pRefList || NULL == pRefList->pRef[0])
772     return false;
773 
774   if (NULL != pCtx->pDecPic) {
775 #if !defined(ENABLE_FRAME_DUMP) // to save complexity, 1/6/2009
776     if ((pParamD->iHighestTemporalId == 0) || (kuiTid < pParamD->iHighestTemporalId))
777 #endif// !ENABLE_FRAME_DUMP
778       // Expanding picture for future reference
779       ExpandReferencingPicture (pCtx->pDecPic->pData, pCtx->pDecPic->iWidthInPixel, pCtx->pDecPic->iHeightInPixel,
780                                 pCtx->pDecPic->iLineSize,
781                                 pCtx->pFuncList->sExpandPicFunc.pfExpandLumaPicture, pCtx->pFuncList->sExpandPicFunc.pfExpandChromaPicture);
782 
783     // move picture in list
784     pCtx->pDecPic->uiTemporalId = pCtx->uiTemporalId;
785     pCtx->pDecPic->uiSpatialId  = pCtx->uiDependencyId;
786     pCtx->pDecPic->iFrameNum    = pParamD->iFrameNum;
787     pCtx->pDecPic->iFramePoc    = pParamD->iPOC;
788     pCtx->pDecPic->bUsedAsRef   = true;
789     pCtx->pDecPic->bIsLongRef   = true;
790     pCtx->pDecPic->bIsSceneLTR  = pLtr->bLTRMarkingFlag || (pCtx->pSvcParam->bEnableLongTermReference
791                                   && pCtx->eSliceType == I_SLICE);
792     pCtx->pDecPic->iLongTermPicNum = pLtr->iCurLtrIdx;
793   }
794   if (pCtx->eSliceType == P_SLICE) {
795     DeleteNonSceneLTR (pCtx);
796     LTRMarkProcessScreen (pCtx);
797     pLtr->bLTRMarkingFlag = false;
798     ++pLtr->uiLtrMarkInterval;
799   } else { // in case IDR currently coding
800     LTRMarkProcessScreen (pCtx);
801     pLtr->iCurLtrIdx = 1;
802     pLtr->iSceneLtrIdx = 1;
803     pLtr->uiLtrMarkInterval = 0;
804     pCtx->pVaa->uiValidLongTermPicIdx = 0;
805   }
806 
807   pCtx->pReferenceStrategy->EndofUpdateRefList();
808   return true;
809 }
810 
WelsBuildRefListScreen(sWelsEncCtx * pCtx,const int32_t iPOC,int32_t iBestLtrRefIdx)811 bool WelsBuildRefListScreen (sWelsEncCtx* pCtx, const int32_t iPOC, int32_t iBestLtrRefIdx) {
812   SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
813   SWelsSvcCodingParam* pParam = pCtx->pSvcParam;
814   SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa);
815   const int32_t iNumRef = pParam->iNumRefFrame;
816   SSpatialLayerInternal* pParamD    = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
817   pCtx->iNumRef0 = 0;
818 
819   if (pCtx->eSliceType != I_SLICE) {
820     int iLtrRefIdx = 0;
821     SPicture* pRefOri = NULL;
822     for (int idx = 0; idx < pVaaExt->iNumOfAvailableRef; idx++) {
823       iLtrRefIdx = pCtx->pVpp->GetRefFrameInfo (idx, pCtx->bCurFrameMarkedAsSceneLtr, pRefOri);
824       if (iLtrRefIdx >= 0 && iLtrRefIdx <= pParam->iLTRRefNum) {
825         SPicture* pRefPic = pRefList->pLongRefList[iLtrRefIdx];
826         if (pRefPic != NULL && pRefPic->bUsedAsRef && pRefPic->bIsLongRef) {
827           if (pRefPic->uiTemporalId <= pCtx->uiTemporalId && (!pCtx->bCurFrameMarkedAsSceneLtr || pRefPic->bIsSceneLTR)) {
828             pCtx->pCurDqLayer->pRefOri[pCtx->iNumRef0] = pRefOri;
829             pCtx->pRefList0[pCtx->iNumRef0++] = pRefPic;
830             WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
831                      "WelsBuildRefListScreen(), current iFrameNum = %d, current Tid = %d, ref iFrameNum = %d, ref uiTemporalId = %d, ref is Scene LTR = %d, LTR count = %d,iNumRef = %d",
832                      pParamD->iFrameNum, pCtx->uiTemporalId,
833                      pRefPic->iFrameNum, pRefPic->uiTemporalId, pRefPic->bIsSceneLTR,
834                      pRefList->uiLongRefCount, iNumRef);
835           }
836         }
837       } else {
838         for (int32_t i = iNumRef ; i >= 0 ; --i) {
839           if (pRefList->pLongRefList[i] == NULL) {
840             continue;
841           } else if (pRefList->pLongRefList[i]->uiTemporalId == 0
842                      || pRefList->pLongRefList[i]->uiTemporalId < pCtx->uiTemporalId) {
843             pCtx->pCurDqLayer->pRefOri[pCtx->iNumRef0] = pRefOri;
844             pCtx->pRefList0[pCtx->iNumRef0++] = pRefList->pLongRefList[i];
845             WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
846                      "WelsBuildRefListScreen(), ref !current iFrameNum = %d, ref iFrameNum = %d,LTR number = %d",
847                      pParamD->iFrameNum, pCtx->pRefList0[pCtx->iNumRef0 - 1]->iFrameNum, pRefList->uiLongRefCount);
848             break;
849           }
850         }
851       }
852     } // end of (int idx = 0; idx < pVaaExt->iNumOfAvailableRef; idx++)
853 
854     WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
855              "WelsBuildRefListScreen(), CurrentFramePoc=%d, isLTR=%d", iPOC, pCtx->bCurFrameMarkedAsSceneLtr);
856     for (int j = 0; j < iNumRef; j++) {
857       SPicture* pARefPicture = pRefList->pLongRefList[j];
858       if (pARefPicture != NULL) {
859         WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
860                  "WelsBuildRefListScreen()\tRefLot[%d]: iPoc=%d, iPictureType=%d, bUsedAsRef=%d, bIsLongRef=%d, bIsSceneLTR=%d, uiTemporalId=%d, iFrameNum=%d, iMarkFrameNum=%d, iLongTermPicNum=%d, uiRecieveConfirmed=%d",
861                  j,
862                  pARefPicture->iFramePoc,
863                  pARefPicture->iPictureType,
864                  pARefPicture->bUsedAsRef,
865                  pARefPicture->bIsLongRef,
866                  pARefPicture->bIsSceneLTR,
867                  pARefPicture->uiTemporalId,
868                  pARefPicture->iFrameNum,
869                  pARefPicture->iMarkFrameNum,
870                  pARefPicture->iLongTermPicNum,
871                  pARefPicture->uiRecieveConfirmed);
872       } else {
873         WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "WelsBuildRefListScreen()\tRefLot[%d]: NULL", j);
874       }
875     }
876   } else {
877     // dealing with IDR
878     WelsResetRefList (pCtx);  //for IDR, SHOULD reset pRef list.
879     ResetLtrState (&pCtx->pLtr[pCtx->uiDependencyId]); //SHOULD update it when IDR.
880     pCtx->pRefList0[0] = NULL;
881   }
882   if (pCtx->iNumRef0 > iNumRef) {
883     pCtx->iNumRef0 = iNumRef;
884   }
885 
886   return (pCtx->iNumRef0 > 0 || pCtx->eSliceType == I_SLICE) ? (true) : (false);
887 }
888 
IsValidFrameNum(const int32_t kiFrameNum)889 static inline bool IsValidFrameNum (const int32_t kiFrameNum) {
890   return (kiFrameNum < (1 << 30)); // TODO: use the original judge first, may be improved
891 }
892 
WelsMarkMMCORefInfoScreen(sWelsEncCtx * pCtx,SLTRState * pLtr,SSlice ** ppSliceList,const int32_t kiCountSliceNum)893 void WelsMarkMMCORefInfoScreen (sWelsEncCtx* pCtx, SLTRState* pLtr,
894                                 SSlice** ppSliceList, const int32_t kiCountSliceNum) {
895   SSlice* pBaseSlice          = ppSliceList[0];
896   SRefPicMarking* pRefPicMark = &pBaseSlice->sSliceHeaderExt.sSliceHeader.sRefMarking;
897   const int32_t iMaxLtrIdx = pCtx->pSvcParam->iNumRefFrame - STR_ROOM - 1;
898 
899   memset (pRefPicMark, 0, sizeof (SRefPicMarking));
900   if (pCtx->pSvcParam->bEnableLongTermReference) {
901     pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount].iMaxLongTermFrameIdx = iMaxLtrIdx;
902     pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount++].iMmcoType = MMCO_SET_MAX_LONG;
903 
904     pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount].iLongTermFrameIdx = pLtr->iCurLtrIdx;
905     pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount++].iMmcoType = MMCO_LONG;
906   }
907 
908   WelsMarkMMCORefInfoWithBase (ppSliceList, pBaseSlice, kiCountSliceNum);
909 }
910 
WelsMarkPicScreen(sWelsEncCtx * pCtx)911 void WelsMarkPicScreen (sWelsEncCtx* pCtx) {
912   SLTRState* pLtr          = &pCtx->pLtr[pCtx->uiDependencyId];
913   int32_t iMaxTid          = WELS_LOG2 (pCtx->pSvcParam->uiGopSize);
914   int32_t iMaxActualLtrIdx = -1;
915   SSpatialLayerInternal* pParamD    = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
916   if (pCtx->pSvcParam->bEnableLongTermReference)
917     iMaxActualLtrIdx = pCtx->pSvcParam->iNumRefFrame - STR_ROOM - 1 -  WELS_MAX (iMaxTid , 1);
918 
919   SRefList* pRefList =  pCtx->ppRefPicListExt[pCtx->uiDependencyId];
920   SPicture** ppLongRefList = pRefList->pLongRefList;
921   const int32_t iNumRef = pCtx->pSvcParam->iNumRefFrame;
922   int32_t i;
923   const int32_t iLongRefNum = iNumRef - STR_ROOM;
924   const bool bIsRefListNotFull = pRefList->uiLongRefCount < iLongRefNum;
925 
926   if (!pCtx->pSvcParam->bEnableLongTermReference) {
927     pLtr->iCurLtrIdx = pCtx->uiTemporalId;
928   } else {
929     if (iMaxActualLtrIdx != -1 && pCtx->uiTemporalId == 0 && pCtx->bCurFrameMarkedAsSceneLtr) {
930       //Scene LTR
931       pLtr->bLTRMarkingFlag = true;
932       pLtr->uiLtrMarkInterval = 0;
933       pLtr->iCurLtrIdx  = pLtr->iSceneLtrIdx % (iMaxActualLtrIdx + 1);
934       pLtr->iSceneLtrIdx++;
935     } else {
936       pLtr->bLTRMarkingFlag = false;
937       //for other LTR
938       if (bIsRefListNotFull) {
939         for (int32_t i = 0; i < iLongRefNum; ++i) {
940           if (pRefList->pLongRefList[i] == NULL) {
941             pLtr->iCurLtrIdx = i   ;
942             break;
943           }
944         }
945       } else {
946         int32_t iRefNum_t[MAX_TEMPORAL_LAYER_NUM] = {0};
947         for (i = 0 ; i < pRefList->uiLongRefCount ; ++i) {
948           if (ppLongRefList[i]->bUsedAsRef && ppLongRefList[i]->bIsLongRef && (!ppLongRefList[i]->bIsSceneLTR)) {
949             ++iRefNum_t[ ppLongRefList[i]->uiTemporalId ];
950           }
951         }
952 
953         int32_t iMaxMultiRefTid = (iMaxTid) ? (iMaxTid - 1) : (0) ;
954         for (i = 0; i < MAX_TEMPORAL_LAYER_NUM ; ++i) {
955           if (iRefNum_t[i] > 1) {
956             iMaxMultiRefTid = i;
957           }
958         }
959         int32_t iLongestDeltaFrameNum = -1;
960         int32_t iMaxFrameNum = (1 << pCtx->pSps->uiLog2MaxFrameNum);
961 
962         for (i = 0 ; i < pRefList->uiLongRefCount ; ++i) {
963           if (ppLongRefList[i]->bUsedAsRef && ppLongRefList[i]->bIsLongRef && (!ppLongRefList[i]->bIsSceneLTR)
964               && iMaxMultiRefTid == ppLongRefList[i]->uiTemporalId) {
965             if (!IsValidFrameNum (ppLongRefList[i]->iFrameNum)) {  // pLtr->iCurLtrIdx must have a value
966               WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "WelsMarkPicScreen, Invalid Frame Number");
967               return;
968             }
969             int32_t iDeltaFrameNum = (pParamD->iFrameNum >= ppLongRefList[i]->iFrameNum)
970                                      ? (pParamD->iFrameNum - ppLongRefList[i]->iFrameNum)
971                                      : (pParamD->iFrameNum + iMaxFrameNum - ppLongRefList[i]->iFrameNum);
972 
973             if (iDeltaFrameNum > iLongestDeltaFrameNum) {
974               pLtr->iCurLtrIdx = ppLongRefList[i]->iLongTermPicNum;
975               iLongestDeltaFrameNum = iDeltaFrameNum;
976             }
977           }
978         }
979       }
980     }
981   }
982 
983   for (i = 0 ; i < MAX_TEMPORAL_LAYER_NUM; ++i) {
984     if ((pCtx->uiTemporalId <  i) || (pCtx->uiTemporalId == 0)) {
985       pLtr->iLastLtrIdx[i] = pLtr->iCurLtrIdx;
986     }
987   }
988 
989   const int32_t iSliceNum = pCtx->pCurDqLayer->iMaxSliceNum;
990 
991   WelsMarkMMCORefInfoScreen (pCtx, pLtr, pCtx->pCurDqLayer->ppSliceInLayer, iSliceNum);
992 
993   return;
994 }
995 
DoNothing(sWelsEncCtx * pointer)996 void DoNothing (sWelsEncCtx* pointer) {
997 }
998 
999 
CreateReferenceStrategy(sWelsEncCtx * pCtx,const EUsageType keUsageType,const bool kbLtrEnabled)1000 IWelsReferenceStrategy*   IWelsReferenceStrategy::CreateReferenceStrategy (sWelsEncCtx* pCtx,
1001     const EUsageType keUsageType,
1002     const bool kbLtrEnabled) {
1003 
1004   IWelsReferenceStrategy* pReferenceStrategy = NULL;
1005   switch (keUsageType) {
1006   case SCREEN_CONTENT_REAL_TIME:
1007     if (kbLtrEnabled) {
1008       pReferenceStrategy = WELS_NEW_OP (CWelsReference_LosslessWithLtr(),
1009                                         CWelsReference_LosslessWithLtr);
1010     } else {
1011       pReferenceStrategy = WELS_NEW_OP (CWelsReference_Screen(),
1012                                         CWelsReference_Screen);
1013     }
1014     WELS_VERIFY_RETURN_IF (NULL, NULL == pReferenceStrategy)
1015     break;
1016   case CAMERA_VIDEO_REAL_TIME:
1017   case CAMERA_VIDEO_NON_REAL_TIME:
1018   default:
1019     pReferenceStrategy = WELS_NEW_OP (CWelsReference_TemporalLayer(),
1020                                       CWelsReference_TemporalLayer);
1021     WELS_VERIFY_RETURN_IF (NULL, NULL == pReferenceStrategy)
1022     break;
1023   }
1024   pReferenceStrategy->Init (pCtx);
1025   return pReferenceStrategy;
1026 }
1027 
Init(sWelsEncCtx * pCtx)1028 void CWelsReference_TemporalLayer::Init (sWelsEncCtx* pCtx) {
1029   m_pEncoderCtx = pCtx;
1030 }
1031 
BuildRefList(const int32_t iPOC,int32_t iBestLtrRefIdx)1032 bool CWelsReference_TemporalLayer::BuildRefList (const int32_t iPOC, int32_t iBestLtrRefIdx) {
1033   return WelsBuildRefList (m_pEncoderCtx, iPOC,  iBestLtrRefIdx);
1034 }
MarkPic()1035 void CWelsReference_TemporalLayer::MarkPic() {
1036   WelsMarkPic (m_pEncoderCtx);
1037 }
UpdateRefList()1038 bool CWelsReference_TemporalLayer::UpdateRefList() {
1039   return WelsUpdateRefList (m_pEncoderCtx);
1040 }
EndofUpdateRefList()1041 void CWelsReference_TemporalLayer::EndofUpdateRefList() {
1042   PrefetchNextBuffer (m_pEncoderCtx);
1043 }
AfterBuildRefList()1044 void CWelsReference_TemporalLayer::AfterBuildRefList() {
1045   DoNothing (m_pEncoderCtx);
1046 }
1047 
BuildRefList(const int32_t iPOC,int32_t iBestLtrRefIdx)1048 bool CWelsReference_Screen::BuildRefList (const int32_t iPOC, int32_t iBestLtrRefIdx) {
1049   return WelsBuildRefList (m_pEncoderCtx, iPOC,  iBestLtrRefIdx);
1050 }
MarkPic()1051 void CWelsReference_Screen::MarkPic() {
1052   WelsMarkPic (m_pEncoderCtx);
1053 }
UpdateRefList()1054 bool CWelsReference_Screen::UpdateRefList() {
1055   return WelsUpdateRefList (m_pEncoderCtx);
1056 }
EndofUpdateRefList()1057 void CWelsReference_Screen::EndofUpdateRefList() {
1058   UpdateSrcPicList (m_pEncoderCtx);
1059 }
AfterBuildRefList()1060 void CWelsReference_Screen::AfterBuildRefList() {
1061   UpdateBlockStatic (m_pEncoderCtx);
1062 }
1063 
BuildRefList(const int32_t iPOC,int32_t iBestLtrRefIdx)1064 bool CWelsReference_LosslessWithLtr::BuildRefList (const int32_t iPOC, int32_t iBestLtrRefIdx) {
1065   return WelsBuildRefListScreen (m_pEncoderCtx, iPOC,  iBestLtrRefIdx);
1066 }
MarkPic()1067 void CWelsReference_LosslessWithLtr::MarkPic() {
1068   WelsMarkPicScreen (m_pEncoderCtx);
1069 }
UpdateRefList()1070 bool CWelsReference_LosslessWithLtr::UpdateRefList() {
1071   return WelsUpdateRefListScreen (m_pEncoderCtx);
1072 }
EndofUpdateRefList()1073 void CWelsReference_LosslessWithLtr::EndofUpdateRefList() {
1074   UpdateSrcPicListLosslessScreenRefSelectionWithLtr (m_pEncoderCtx);
1075 }
1076 } // namespace WelsEnc
1077 
1078