Commit 98bc7cbb for openh264

commit 98bc7cbbeb7381c94ef8f9a5d158327abbf6b8b9
Author: BenzhengZhang <140143892+BenzhengZhang@users.noreply.github.com>
Date:   Mon Aug 10 18:01:46 2026 +0800

    decoder: guard GetColocatedMb null colocPic before wait (#3978)

    Co-authored-by: benzzhan <benzzhan@cisco.com>

diff --git a/codec/decoder/core/src/mv_pred.cpp b/codec/decoder/core/src/mv_pred.cpp
index 28b4feb9..b2d122d0 100644
--- a/codec/decoder/core/src/mv_pred.cpp
+++ b/codec/decoder/core/src/mv_pred.cpp
@@ -315,6 +315,12 @@ int32_t GetColocatedMb (PWelsDecoderContext pCtx, MbType& mbType, SubMbType& sub
   mbType = GetMbType (pCurDqLayer)[iMbXy];

   PPicture colocPic = pCtx->sRefPic.pRefList[LIST_1][0];
+  if (colocPic == NULL) {
+    SLogContext* pLogCtx = & (pCtx->sLogCtx);
+    WelsLog (pLogCtx, WELS_LOG_ERROR, "Colocated Ref Picture for B-Slice is lost, B-Slice decoding cannot be continued!");
+    return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_DATA, ERR_INFO_REFERENCE_PIC_LOST);
+  }
+
   if (GetThreadCount (pCtx) > 1) {
     if (16 * pCurDqLayer->iMbY > pCtx->lastReadyHeightOffset[1][0]) {
       if (colocPic->pReadyEvent[pCurDqLayer->iMbY].isSignaled != 1) {
@@ -324,12 +330,6 @@ int32_t GetColocatedMb (PWelsDecoderContext pCtx, MbType& mbType, SubMbType& sub
     }
   }

-  if (colocPic == NULL) {
-    SLogContext* pLogCtx = & (pCtx->sLogCtx);
-    WelsLog (pLogCtx, WELS_LOG_ERROR, "Colocated Ref Picture for B-Slice is lost, B-Slice decoding cannot be continued!");
-    return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_DATA, ERR_INFO_REFERENCE_PIC_LOST);
-  }
-
   MbType coloc_mbType = colocPic->pMbType[iMbXy];
   if (coloc_mbType == MB_TYPE_SKIP) {
     //This indicates the colocated MB is P SKIP MB
diff --git a/test/decoder/DecUT_PredMv.cpp b/test/decoder/DecUT_PredMv.cpp
index 4a7d6a86..aca9e001 100644
--- a/test/decoder/DecUT_PredMv.cpp
+++ b/test/decoder/DecUT_PredMv.cpp
@@ -7,6 +7,13 @@

 using namespace WelsDec;

+static void DummyDecoderLog (void* pCtx, const int32_t iLevel, const char* kpFmt, va_list argv) {
+  (void)pCtx;
+  (void)iLevel;
+  (void)kpFmt;
+  (void)argv;
+}
+
 //Anchor functions
 #define REF_NOT_AVAIL    -2
 #define REF_NOT_IN_LIST  -1  //intra
@@ -668,3 +675,30 @@ TEST (PredMvTest, PredSkipMvFromNeighbor) {

   FreeLayerData (&sDqLayer);
 }
+
+TEST (PredMvTest, GetColocatedMbNullRefPicReturnsErrorBeforeWait) {
+  SWelsDecoderContext sCtx;
+  SDqLayer sDqLayer;
+  SWelsDecoderThreadCTX sThreadCtx;
+  uint32_t uiMbType = MB_TYPE_16x16;
+  MbType mbType = MB_TYPE_16x16;
+  SubMbType subMbType = SUB_MB_TYPE_8x8;
+
+  memset (&sCtx, 0, sizeof (sCtx));
+  memset (&sDqLayer, 0, sizeof (sDqLayer));
+  memset (&sThreadCtx, 0, sizeof (sThreadCtx));
+
+  sDqLayer.iMbXyIndex = 0;
+  sDqLayer.iMbY = 1;
+  sDqLayer.pMbType = &uiMbType;
+  sCtx.pCurDqLayer = &sDqLayer;
+
+  sThreadCtx.sThreadInfo.uiThrMaxNum = 2;
+  sCtx.pThreadCtx = &sThreadCtx;
+  sCtx.sLogCtx.pfLog = DummyDecoderLog;
+  sCtx.lastReadyHeightOffset[1][0] = 0;
+  sCtx.sRefPic.pRefList[LIST_1][0] = NULL;
+
+  const int32_t iRet = GetColocatedMb (&sCtx, mbType, subMbType);
+  EXPECT_EQ (GENERATE_ERROR_NO (ERR_LEVEL_SLICE_DATA, ERR_INFO_REFERENCE_PIC_LOST), iRet);
+}