shithub: openh264

Download patch

ref: fc895c13ceb0ffc533458c10d8e03821466a6b14
parent: 054b8eeb3abcb19ae2eb39c9d802b21ea2648974
author: dongzha <dongzha@DONGZHA-WS04.cisco.com>
date: Thu Dec 4 12:07:10 EST 2014

fix grey picture when resolution is the same

--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -94,6 +94,119 @@
   return 0;
 }
 
+static int32_t IncreasePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiOldSize,
+                              const int32_t kiPicWidth, const int32_t kiPicHeight, const int32_t kiNewSize) {
+  PPicBuff pPicOldBuf = *ppPicBuf;
+  PPicBuff pPicNewBuf = NULL;
+  int32_t iPicIdx = 0;
+  if (kiOldSize<=0 || kiNewSize <= 0 || kiPicWidth <= 0 || kiPicHeight <= 0) {
+    return 1;
+  }
+
+  pPicNewBuf	= (PPicBuff)WelsMalloc (sizeof (SPicBuff), "PPicBuff");
+
+  if (NULL == pPicNewBuf) {
+    return 1;
+  }
+
+  pPicNewBuf->ppPic = (PPicture*)WelsMalloc (kiNewSize * sizeof (PPicture), "PPicture*");
+
+  if (NULL == pPicNewBuf->ppPic) {
+    return 1;
+  }
+  // copy old PicBuf to new PicBuf
+  memcpy(pPicNewBuf->ppPic, pPicOldBuf->ppPic, kiOldSize * sizeof(PPicture));
+  // initialize context in queue
+  pPicNewBuf->iCapacity	 = kiNewSize;
+  pPicNewBuf->iCurrentIdx = pPicOldBuf->iCurrentIdx;
+  *ppPicBuf			 = pPicNewBuf;
+
+  // increase new PicBuf
+  for (iPicIdx = kiOldSize; iPicIdx < kiNewSize; ++ iPicIdx) {
+    PPicture pPic = AllocPicture (pCtx, kiPicWidth, kiPicHeight);
+    if (NULL == pPic) {
+      return 1;
+    }
+    pPicNewBuf->ppPic[iPicIdx] = pPic;
+  }
+
+  // remove old PicBuf
+  if (pPicOldBuf->ppPic != NULL) {
+    WelsFree (pPicOldBuf->ppPic, "pPicOldBuf->queue");
+    pPicOldBuf->ppPic	= NULL;
+  }
+  pPicOldBuf->iCapacity	= 0;
+  pPicOldBuf->iCurrentIdx = 0;
+  WelsFree (pPicOldBuf, "pPicOldBuf");
+
+  return 0;
+}
+
+static int32_t DecreasePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiOldSize,
+                              const int32_t kiPicWidth, const int32_t kiPicHeight, const int32_t kiNewSize) {
+  PPicBuff pPicOldBuf = *ppPicBuf;
+  PPicBuff pPicNewBuf = NULL;
+  int32_t iPicIdx = 0;
+  if (kiOldSize<=0 || kiNewSize <= 0 || kiPicWidth <= 0 || kiPicHeight <= 0) {
+    return 1;
+  }
+
+  pPicNewBuf	= (PPicBuff)WelsMalloc (sizeof (SPicBuff), "PPicBuff");
+
+  if (NULL == pPicNewBuf) {
+    return 1;
+  }
+
+  pPicNewBuf->ppPic = (PPicture*)WelsMalloc (kiNewSize * sizeof (PPicture), "PPicture*");
+
+  if (NULL == pPicNewBuf->ppPic) {
+    return 1;
+  }
+
+  int32_t iPrevPicIdx = -1;
+  for (iPrevPicIdx = 0; iPrevPicIdx < kiOldSize; ++iPrevPicIdx) {
+    if(pCtx->pPreviousDecodedPictureInDpb == pPicOldBuf->ppPic[iPrevPicIdx]) {
+      break;
+    }
+  }
+  int32_t iDelIdx;
+  if(iPrevPicIdx < kiOldSize && iPrevPicIdx >= kiNewSize) {
+    // found pPreviousDecodedPictureInDpb, 
+    pPicNewBuf->ppPic[0] = pPicOldBuf->ppPic[iPrevPicIdx];
+    pPicNewBuf->iCurrentIdx = 0;
+    memcpy(pPicNewBuf->ppPic + 1, pPicOldBuf->ppPic, (kiNewSize - 1) * sizeof(PPicture));
+    iDelIdx = kiNewSize - 1;
+  } else {
+    memcpy(pPicNewBuf->ppPic, pPicOldBuf->ppPic, kiNewSize * sizeof(PPicture));
+    pPicNewBuf->iCurrentIdx = iPrevPicIdx < kiNewSize? iPrevPicIdx : 0;
+    iDelIdx = kiNewSize;
+  }
+
+  for(iPicIdx = iDelIdx; iPicIdx < kiOldSize; iPicIdx++) {
+    if(iPrevPicIdx != iPicIdx) {
+      if (pPicOldBuf->ppPic[iPicIdx] != NULL) {
+        FreePicture (pPicOldBuf->ppPic[iPicIdx]);
+        pPicOldBuf->ppPic[iPicIdx] = NULL;
+       }
+    }
+  }
+
+  // initialize context in queue
+  pPicNewBuf->iCapacity	 = kiNewSize;
+  *ppPicBuf			 = pPicNewBuf;
+
+  // remove old PicBuf
+  if (pPicOldBuf->ppPic != NULL) {
+    WelsFree (pPicOldBuf->ppPic, "pPicOldBuf->queue");
+    pPicOldBuf->ppPic	= NULL;
+  }
+  pPicOldBuf->iCapacity	= 0;
+  pPicOldBuf->iCurrentIdx = 0;
+  WelsFree (pPicOldBuf, "pPicOldBuf");
+
+  return 0;
+}
+
 static void DestroyPicBuff (PPicBuff* ppPicBuf) {
   PPicBuff pPicBuf = NULL;
 
@@ -225,18 +338,29 @@
   // sync update pRefList
   WelsResetRefPic (pCtx);	// added to sync update ref list due to pictures are free
 
-  // for Recycled_Pic_Queue
-  for (iListIdx = LIST_0; iListIdx < LIST_A; ++ iListIdx) {
-    PPicBuff* ppPic = &pCtx->pPicBuff[iListIdx];
-    if (NULL != ppPic && NULL != *ppPic) {
-      DestroyPicBuff (ppPic);
+  if(pCtx->bHaveGotMemory && (kiPicWidth == pCtx->iImgWidthInPixel && kiPicHeight == pCtx->iImgHeightInPixel)
+                         && pCtx->pPicBuff[LIST_0] != NULL && pCtx->pPicBuff[LIST_0]->iCapacity != iPicQueueSize) {
+      // currently only active for LIST_0 due to have no B frames
+    if (pCtx->pPicBuff[LIST_0]->iCapacity < iPicQueueSize) {
+      iErr = IncreasePicBuff (pCtx, &pCtx->pPicBuff[LIST_0], pCtx->pPicBuff[LIST_0]->iCapacity, kiPicWidth, kiPicHeight, iPicQueueSize);
+    } else {
+      iErr = DecreasePicBuff (pCtx, &pCtx->pPicBuff[LIST_0], pCtx->pPicBuff[LIST_0]->iCapacity, kiPicWidth, kiPicHeight, iPicQueueSize);
     }
-  }
+  } else {
+      // for Recycled_Pic_Queue
+      for (iListIdx = LIST_0; iListIdx < LIST_A; ++ iListIdx) {
+        PPicBuff* ppPic = &pCtx->pPicBuff[iListIdx];
+        if (NULL != ppPic && NULL != *ppPic) {
+          DestroyPicBuff (ppPic);
+        }
+      }
 
-  pCtx->pPreviousDecodedPictureInDpb = NULL;
+      pCtx->pPreviousDecodedPictureInDpb = NULL;
 
-  // currently only active for LIST_0 due to have no B frames
-  iErr = CreatePicBuff (pCtx, &pCtx->pPicBuff[LIST_0], iPicQueueSize, kiPicWidth, kiPicHeight);
+      // currently only active for LIST_0 due to have no B frames
+      iErr = CreatePicBuff (pCtx, &pCtx->pPicBuff[LIST_0], iPicQueueSize, kiPicWidth, kiPicHeight);
+  }
+
   if (iErr != ERR_NONE)
     return iErr;