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