videoeditorengine/h263decoder/src/decvp_mpeg.cpp
changeset 0 951a5db380a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/h263decoder/src/decvp_mpeg.cpp	Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,653 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - Initial contribution
+*
+* Contributors:
+* Ixonos Plc
+*
+* Description:  
+* Video packet decoding module (MPEG-4).
+*
+*/
+
+
+/*
+ * Includes
+ */
+#include "h263dConfig.h"
+#include "decvp_mpeg.h"
+#include "block.h"
+#include "debug.h"
+#include "decmbs.h"
+#include "stckheap.h"
+#include "sync.h"
+#include "viddemux.h"
+#include "biblin.h"
+/* MVE */
+#include "MPEG4Transcoder.h"
+
+/*
+ * Global functions
+ */
+
+/* {{-output"dvpGetAndDecodeVideoPacketHeader.txt"}} */
+/*
+ * dvpGetAndDecodeVideoPacketHeader
+ *    
+ *
+ * Parameters:
+ *    inParam                    input parameters
+ *    inOutParam                 input/output parameters, these parameters
+ *                               may be modified in the function
+ *
+ * Function:
+ *    This function gets and decodes a Video Packet header at the 
+ *    current position of the bit buffer. It checks its correctness and 
+ *    if it fits to the sequence of VPs, and does the necessary actions for 
+ *    correction.
+ *
+ * Returns:
+ *    >= 0                       the function was successful
+ *    < 0                        an error occured
+ *
+ */
+
+int dvpGetAndDecodeVideoPacketHeader(
+   const dvpVPInParam_t *inParam,
+   dvpVPInOutParam_t *inOutParam)
+/* {{-output"dvpGetAndDecodeVideoPacketHeader.txt"}} */
+{
+   int16 error = 0;
+   vdxGetVideoPacketHeaderInputParam_t vdxParam;
+   vdxVideoPacketHeader_t header;
+   bibBuffer_t *inBuffer = inParam->inBuffer;
+   int bitErrorIndication = 0, retVal, fLostSegment = FALSE;
+
+   /* 
+    * Get VP header 
+    */
+
+   vdxParam.fcode_forward = inParam->pictParam->fcode_forward;
+   vdxParam.time_increment_resolution = inParam->pictParam->time_increment_resolution;
+   vdxParam.numOfMBs = inParam->pictParam->numMBsInGOB;
+
+   retVal = vdxGetVideoPacketHeader(inBuffer, &vdxParam, &header, &bitErrorIndication);
+   if (retVal < 0) {
+     return DGOB_ERR;
+   } else if (retVal > 0) {
+      deb("dvpGetAndDecodeVideoPacketHeader: ERROR - vdxGetVideoPacketHeader failed.\n");
+      goto headerFailure;
+   }
+
+
+   /*
+    * Check header validity
+    */
+
+   if (header.currMBNum == 0 || header.currMBNum >= inParam->pictParam->numMBsInGOB) {
+      deb("dvpGetAndDecodeVideoPacketHeader: ERROR - too big currMBNum.\n");
+      goto headerFailure;
+   }
+   
+   /* quant can not be zero */
+   if(header.quant == 0) {
+      goto headerFailure;
+   }
+
+   if (header.fHEC) {
+
+      if (header.time_base_incr < 0 || header.time_base_incr > 60) {
+         if (bitErrorIndication) {
+            goto headerFailure;
+         }
+      }
+
+      /* fcode can have only the valid values 1..7 */
+      if (header.coding_type == VDX_VOP_TYPE_P) 
+         if (header.fcode_forward == 0) {
+            goto headerFailure;
+         }
+
+      if (!inParam->fVOPHeaderCorrupted) {
+
+         if ((inParam->pictParam->pictureType != header.coding_type) ||
+            (inParam->pictParam->time_base_incr != header.time_base_incr) ||
+            (inParam->pictParam->time_inc != header.time_inc)) {
+            deb("dvpGetAndDecodeVideoPacketHeader: ERROR - Parameter change VOP<->VP header.\n");
+            goto headerFailure;
+         }
+      }
+   }
+   if (inParam->fVOPHeaderCorrupted) {
+      /* Get the coding type parameter since it is needed in the concealment before the other updates */
+      if (header.fHEC) {
+         inParam->pictParam->pictureType = header.coding_type;
+      }
+   }
+   if (header.currMBNum != inOutParam->currMBNum) {
+      if ( header.currMBNum > inOutParam->currMBNum && bitErrorIndication == 0) {
+
+         fLostSegment = TRUE;
+         goto headerFailure;
+
+      } else if (header.currMBNum < inOutParam->currMBNum) {
+         deb("dvpGetAndDecodeVideoPacketHeader: ERROR - MB counting is out of sync.\n");
+         goto headerFailure;
+      }
+   }
+
+   /*
+    * Update parameters
+    */
+
+   inOutParam->currMBNum = header.currMBNum;
+   inOutParam->quant = header.quant;
+
+   if (inParam->fVOPHeaderCorrupted) {
+      if (header.fHEC) {
+         inParam->pictParam->mod_time_base += inParam->pictParam->time_base_incr = header.time_base_incr;
+         
+         inParam->pictParam->time_inc = header.time_inc;
+
+         inOutParam->frameNum = (int) ((inParam->pictParam->mod_time_base + 
+            ((double) header.time_inc) / ((double) inParam->pictParam->time_increment_resolution)) *
+            30.0 + 0.001);
+
+         inParam->pictParam->tr = inOutParam->frameNum % 256;
+         inParam->pictParam->pictureType = header.coding_type;
+
+         inParam->pictParam->intra_dc_vlc_thr = header.intra_dc_vlc_thr;
+
+         if (header.coding_type == VDX_VOP_TYPE_P)
+             if (inParam->pictParam->fcode_forward != header.fcode_forward) {
+                 /* Initialize once to count parameters for the mvc module */
+                 int r_size, scale_factor;
+                 
+                 inParam->pictParam->fcode_forward = header.fcode_forward;
+
+                 inOutParam->mvcData->f_code = inParam->pictParam->fcode_forward;
+                 r_size = inParam->pictParam->fcode_forward - 1;
+                 scale_factor = (1 << r_size);
+                 inOutParam->mvcData->range = 160 * scale_factor;
+             }
+      } else {
+         /* seek next PSC, VP start code is not good enough */
+         sncRewindAndSeekNewMPEGSync(-1, inBuffer, 0, &error);
+         return DGOB_OK_BUT_BIT_ERROR;
+      }
+   }
+   
+   if (fLostSegment)
+       return DGOB_OK_BUT_BIT_ERROR;
+   else
+       return DGOB_OK;
+
+   headerFailure:
+      sncRewindAndSeekNewMPEGSync(-1, inBuffer, inParam->pictParam->fcode_forward, &error);
+     
+     if (error && error != ERR_BIB_NOT_ENOUGH_DATA)
+         return DGOB_ERR;
+      return DGOB_OK_BUT_BIT_ERROR;
+}
+
+
+/* {{-output"dvpGetAndDecodeVideoPacketContents.txt"}} */
+/*
+ * dvpGetAndDecodeVideoPacketContents
+ *    
+ *
+ * Parameters:
+ *    inParam                    input parameters
+ *    fGetNewReferenceFrame      non-zero if a new reference frame must be
+ *                               requested from the image store, otherwise 0
+ *    inOutParam                 input/output parameters, these parameters
+ *                               may be modified in the function
+ *
+ * Function:
+ *    This function gets and decodes the contents of a Video Packet
+ *    after the header of the VP (either VP header or picture
+ *    header) is already got and processed. It works MB-by-MB or if VP
+ *    is data partitioned calls the corresponding decoding functions.
+ *    Error concealment for the missing (not decodable) MBs in a P-frame
+ *    is called.
+ *
+ * Returns:
+ *    >= 0                       the function was successful
+ *    < 0                        an error occured
+ *
+ */
+
+int dvpGetAndDecodeVideoPacketContents(
+   const dvpVPInParam_t *inParam,
+   int fGetNewReferenceFrame,
+   dvpVPInOutParam_t *inOutParam, CMPEG4Transcoder *hTranscoder)
+/* {{-output"dvpGetAndDecodeVideoPacketContents.txt"}} */
+{
+   int16 error = 0;
+   int bitErrorIndication = 0;
+   dmbPFrameMBInParam_t dpmbi;
+   dmbPFrameMBInOutParam_t dpmbio;
+   dmbIFrameMBInParam_t dimbi;
+   dmbIFrameMBInOutParam_t dimbio;
+   int yPosInMBs, xPosInMBs = 0;
+   bibBuffer_t *inBuffer;
+   bibBuffer_t 
+       *outBuffer;        /* Output bit buffer instance */
+   
+   bibBufferEdit_t              
+       *bufEdit; 
+   
+   int colorEffect; 
+   TBool getDecodedFrame;
+
+
+   int fSegmentCorrupted = 0;
+
+   int dmbRetValue;
+   int sncCode = SNC_NO_SYNC;
+   int lastMBNumInVP = 0;
+   int startMB = inOutParam->currMBNum;
+
+   SOH_DEFINE(blcDiffMB_t, pDiffMB); /* Storage for the previous difference blocks */
+  
+   SOH_ALLOC(blcDiffMB_t, pDiffMB);
+
+   if (pDiffMB == NULL) {
+      deb("dvpGetAndDecodeVideoPacketContents: SOH_ALLOC failed.\n");
+      goto unexpectedError;
+   }
+
+   pDiffMB->cbpy = 0;
+
+   inBuffer = inParam->inBuffer;
+   outBuffer = inParam->outBuffer;
+   bufEdit = inParam->bufEdit;
+   colorEffect = inParam->iColorEffect;
+   getDecodedFrame = inParam->iGetDecodedFrame;
+
+   /* If the reference frame changed */
+   if (fGetNewReferenceFrame) {
+      vdeIms_t *store = inOutParam->imageStore;
+      vdeImsItem_t *imsItem;
+      vdeImb_t *imb;
+      int width, height;
+
+     if (vdeImsGetReference(store, VDEIMS_REF_LATEST, 0, &imsItem) < 0) {
+        deb("dvpGetAndDecodeVideoPacketContents: ERROR - vdeImsGetReference "
+           "failed.\n");
+        goto unexpectedError;
+     }
+
+      /* If no reference frame available */
+      if (!imsItem) {
+         /* Treat the situation like a decoding error.*/
+         deb("dvpGetAndDecodeVideoPacketContents: Warning - no reference frame "
+            "available.\n");
+         goto headerFailure;
+      }
+
+      if (vdeImsStoreItemToImageBuffer(imsItem, &imb) < 0) {
+         deb("dvpGetAndDecodeVideoPacketContents: ERROR - vdeImsStoreItemToImageBuffer "
+            "failed.\n");
+         goto unexpectedError;
+      }
+
+      if (vdeImbYUV(imb, &inOutParam->refY, &inOutParam->refU, 
+         &inOutParam->refV, &width, &height) < 0) {
+         deb("dvpGetAndDecodeVideoPacketContents: ERROR - vdeImbYUV "
+            "failed.\n");
+         goto unexpectedError;
+      }
+   }
+
+   xPosInMBs = (inOutParam->currMBNum % inParam->pictParam->numMBsInMBLine);
+   yPosInMBs = (inOutParam->currMBNum / inParam->pictParam->numMBsInMBLine);
+
+   /* if VOP header corrupted and first VP -> exit */
+   if(inParam->fVOPHeaderCorrupted && inOutParam->currMBNum==0) {
+      fSegmentCorrupted = 1;
+      goto exitWhenVOPHeaderCorrupted;
+   }
+
+   /* in case of an I-VOP */
+   if (inParam->pictParam->pictureType == VDX_VOP_TYPE_I) {
+      dimbi.inBuffer = inBuffer;
+      dimbi.outBuffer = outBuffer;
+      dimbi.bufEdit = bufEdit;
+      dimbi.iColorEffect = colorEffect;
+      dimbi.iGetDecodedFrame = getDecodedFrame;
+
+      dimbi.pictParam = inParam->pictParam;
+
+      dimbi.xPosInMBs = xPosInMBs;
+      dimbi.yPosInMBs = yPosInMBs;
+
+      dimbio.currMBNum = inOutParam->currMBNum;
+      dimbio.currMBNumInVP = 0;
+
+     dimbio.aicData = inOutParam->aicData;
+
+      dimbio.fCodedMBs = inOutParam->fCodedMBs;
+      dimbio.numOfCodedMBs = inOutParam->numOfCodedMBs;
+      dimbio.quant = inOutParam->quant;
+     
+      /* YUV pointers */
+     {
+      int32 yOffset, uvOffset;
+   
+      yOffset = inParam->pictParam->lumMemWidth * dimbi.yPosInMBs + dimbi.xPosInMBs;
+      uvOffset = (inParam->pictParam->lumMemWidth >> 1) * dimbi.yPosInMBs + dimbi.xPosInMBs;
+
+      if ( inOutParam->currPY != NULL )
+        {
+          dimbio.yMBInFrame = inOutParam->currPY + (yOffset << 4);
+          dimbio.uBlockInFrame = inOutParam->currPU + (uvOffset << 3);
+          dimbio.vBlockInFrame = inOutParam->currPV + (uvOffset << 3);
+        }
+      else
+        {
+          dimbio.yMBInFrame = NULL;
+          dimbio.uBlockInFrame = NULL;
+          dimbio.vBlockInFrame = NULL;
+        }
+     }
+   }
+   /* in case of a P-VOP */
+   else {
+      dpmbi.inBuffer = inBuffer;
+      dpmbi.outBuffer = outBuffer;
+      dpmbi.bufEdit = bufEdit;
+      dpmbi.iColorEffect = colorEffect;
+      dpmbi.iGetDecodedFrame = getDecodedFrame;
+
+      dpmbi.pictParam = inParam->pictParam;
+
+      dpmbi.xPosInMBs = xPosInMBs;
+      dpmbi.yPosInMBs = yPosInMBs;
+
+      dpmbi.refY = inOutParam->refY;
+      dpmbi.refU = inOutParam->refU;
+      dpmbi.refV = inOutParam->refV;
+      dpmbi.currPY = inOutParam->currPY;
+      dpmbi.currPU = inOutParam->currPU;
+      dpmbi.currPV = inOutParam->currPV;
+
+      dpmbio.currMBNum = inOutParam->currMBNum;
+      dpmbio.currMBNumInVP = 0;
+
+      dpmbio.fCodedMBs = inOutParam->fCodedMBs;
+      dpmbio.numOfCodedMBs = inOutParam->numOfCodedMBs;
+      dpmbio.quant = inOutParam->quant;
+
+     dpmbio.aicData = inOutParam->aicData;
+
+     dpmbio.mvcData = inOutParam->mvcData;
+      dpmbio.diffMB = pDiffMB;
+
+      /* YUV pointers */
+     {
+      int32 yOffset, uvOffset;
+   
+      yOffset = inParam->pictParam->lumMemWidth * dpmbi.yPosInMBs + dpmbi.xPosInMBs;
+      uvOffset = (inParam->pictParam->lumMemWidth >> 1) * dpmbi.yPosInMBs + dpmbi.xPosInMBs;
+
+      if ( inOutParam->currPY != NULL )
+        {
+          dpmbio.yMBInFrame = inOutParam->currPY + (yOffset << 4);
+          dpmbio.uBlockInFrame = inOutParam->currPU + (uvOffset << 3);
+          dpmbio.vBlockInFrame = inOutParam->currPV + (uvOffset << 3);
+        }
+      else
+        {
+          dimbio.yMBInFrame = NULL;
+          dimbio.uBlockInFrame = NULL;
+          dimbio.vBlockInFrame = NULL;
+        }
+     }
+   }
+
+   /* Decode multiple Macroblocks until a resync_marker is found or error occurs */
+   while (inParam->pictParam->numMBsInGOB != inOutParam->currMBNum && 
+         sncCode != SNC_VIDPACK && sncCode != SNC_VOP) {
+
+       /* MVE */
+       hTranscoder->BeginOneMB((inParam->pictParam->pictureType == VDX_VOP_TYPE_I) ? dimbio.currMBNum : dpmbio.currMBNum );
+       
+     /* decode an I-frame MB */
+      if (inParam->pictParam->pictureType == VDX_VOP_TYPE_I) {
+         
+         if(inParam->pictParam->data_partitioned) {
+
+            dmbRetValue = dmbsGetAndDecodeIMBsDataPartitioned(&dimbi, &dimbio,
+               inOutParam->quantParams, hTranscoder);
+
+            if (dmbRetValue < 0)
+               goto unexpectedError;
+            
+            inOutParam->currMBNum = dimbio.currMBNum;
+
+            /* Video Packet corrupted */
+            if ( fSegmentCorrupted )
+               break;
+
+         } else {
+
+            dmbRetValue = dmbGetAndDecodeIFrameMB(&dimbi, &dimbio, 1, hTranscoder);
+            
+            if (dmbRetValue < 0)
+               goto unexpectedError;
+            else if (dmbRetValue == DMB_BIT_ERR ) {
+               /* Video Packet corrupted */
+               fSegmentCorrupted = 1;
+               break;
+            }
+
+            /* Store quantizer */
+            inOutParam->quantParams[dimbio.currMBNum] = dimbio.quant;
+
+            /* increment the frame pointers and MB counters */
+            dimbio.currMBNum++;
+            dimbio.currMBNumInVP++;
+
+            if ( dimbio.yMBInFrame != NULL )
+            {
+                dimbio.yMBInFrame += 16;
+                dimbio.uBlockInFrame += 8;
+                dimbio.vBlockInFrame += 8;
+            }
+            dimbi.xPosInMBs++;
+
+            if (dimbi.xPosInMBs == inParam->pictParam->numMBsInMBLine) {
+              if ( dimbio.yMBInFrame != NULL )
+                {
+                   dimbio.yMBInFrame += 15 * inParam->pictParam->lumMemWidth;
+                   dimbio.uBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1);
+                   dimbio.vBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1);
+                }
+               dimbi.xPosInMBs = 0;
+               dimbi.yPosInMBs++;
+            }
+
+            inOutParam->currMBNum = dimbio.currMBNum;
+         }
+
+         /* decode a P-frame MB */
+     } else {
+
+         if(inParam->pictParam->data_partitioned) {
+
+            dmbRetValue = dmbsGetAndDecodePMBsDataPartitioned(&dpmbi, &dpmbio,
+               inOutParam->quantParams, hTranscoder);
+
+            if (dmbRetValue < 0)
+               goto unexpectedError;
+
+            inOutParam->currMBNum = dpmbio.currMBNum;
+            lastMBNumInVP = dpmbio.currMBNumInVP;
+
+            /* Video Packet corrupted */
+            if ( fSegmentCorrupted )
+               break;
+
+         } else {
+
+            dmbRetValue = dmbGetAndDecodePFrameMB(&dpmbi, &dpmbio, 1, hTranscoder);
+            
+            if (dmbRetValue < 0)
+               goto unexpectedError;
+            else if (dmbRetValue == DMB_BIT_ERR ) {
+               /* Video Packet corrupted */
+               fSegmentCorrupted = 1;
+               break;
+            }
+            
+            /* Store quantizer */
+            inOutParam->quantParams[dpmbio.currMBNum] = dpmbio.quant;
+
+            /* increment the frame pointers and MB counters */
+            dpmbio.currMBNum++;
+            dpmbio.currMBNumInVP++;
+
+            if ( dpmbio.yMBInFrame != NULL )
+              {
+                dpmbio.yMBInFrame += 16;
+                dpmbio.uBlockInFrame += 8;
+                dpmbio.vBlockInFrame += 8;
+              }
+            dpmbi.xPosInMBs++;
+
+            if (dpmbi.xPosInMBs == inParam->pictParam->numMBsInMBLine) {
+                if ( dpmbio.yMBInFrame != NULL )
+                  {
+                   dpmbio.yMBInFrame += 15 * inParam->pictParam->lumMemWidth;
+                   dpmbio.uBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1);
+                   dpmbio.vBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1);
+                  }
+               dpmbi.xPosInMBs = 0;
+               dpmbi.yPosInMBs++;
+            }
+
+            inOutParam->currMBNum = dpmbio.currMBNum;
+         }
+     }
+
+     /* check for a resync_marker */
+     sncCode = sncCheckMpegSync(inBuffer, inParam->pictParam->fcode_forward, &error);
+     
+     /* If sncCheckMpegSync failed */
+     if (error && error != ERR_BIB_NOT_ENOUGH_DATA) {
+         deb1p("dvpGetAndDecodeVideoPacketContents: ERROR - sncCheckSync returned %d.\n", error);
+         goto unexpectedError;
+         
+     } else 
+         /* If buffer ends (in one-frame-per-one-buffer case) */
+         if (sncCode == SNC_EOB ||
+             sncCode == SNC_STUFFING ||
+             error == ERR_BIB_NOT_ENOUGH_DATA) {
+             break; 
+         }
+     
+   }
+
+
+// <--
+
+   inOutParam->numOfCodedMBs = (inParam->pictParam->pictureType != VDX_VOP_TYPE_I) ? 
+        dpmbio.numOfCodedMBs : dimbio.numOfCodedMBs;
+   
+   if (fSegmentCorrupted) {
+      u_int32 nextVPBitPos;
+
+      /* find the next resync marker, to get the number of MBs in the current VP */
+      sncCode = sncRewindAndSeekNewMPEGSync(-1, inBuffer, inParam->pictParam->fcode_forward, &error);
+      if (error && error != ERR_BIB_NOT_ENOUGH_DATA) {
+         goto unexpectedError;
+      } else if (sncCode == SNC_EOB) {
+         goto exitFunction;
+      }
+
+      nextVPBitPos = bibNumberOfFlushedBits(inParam->inBuffer);
+
+      /* if the lastMBNumInVP was not yet read */
+      if (inParam->pictParam->pictureType == VDX_VOP_TYPE_I || 
+         !inParam->pictParam->data_partitioned || 
+         lastMBNumInVP == 0) { 
+
+         /* if VP header is found: read it, and get last MB number in current vop */
+         if (sncCode == SNC_VIDPACK) {
+            vdxVideoPacketHeader_t header;
+            vdxGetVideoPacketHeaderInputParam_t vdxParam;
+            int retValue;
+            
+            vdxParam.fcode_forward = inParam->pictParam->fcode_forward;
+            vdxParam.time_increment_resolution = inParam->pictParam->time_increment_resolution;
+            vdxParam.numOfMBs = inParam->pictParam->numMBsInGOB;
+            
+            retValue = vdxGetVideoPacketHeader(inParam->inBuffer, &vdxParam, &header, &bitErrorIndication);
+            if (retValue < 0) {
+               goto unexpectedError;
+            } else if (retValue == VDX_OK_BUT_BIT_ERROR) {
+               /* If bit error occurred */
+               goto headerFailure;
+            }
+            
+            /* rewind the bits to the beginning of the VP header */
+            bibRewindBits(bibNumberOfFlushedBits(inParam->inBuffer) - nextVPBitPos,
+               inParam->inBuffer, &error);
+            
+            lastMBNumInVP = header.currMBNum;
+            
+         } else {
+            lastMBNumInVP = inParam->pictParam->numMBsInGOB;
+         }
+      }
+
+      /* if possibly the next VP header is damaged (it gives MB index which is smaller than the start of the current one */
+      if (lastMBNumInVP <= startMB || lastMBNumInVP > inParam->pictParam->numMBsInGOB)
+         goto exitFunction;
+
+      /* if the MB counting due to error overran the next VP header's value */
+      if (inOutParam->currMBNum > lastMBNumInVP)
+         inOutParam->currMBNum = VDC_MAX(lastMBNumInVP-3,startMB);
+      
+      /* if not all the MBs have been predicted due to error */
+      else if (inOutParam->currMBNum < lastMBNumInVP)
+         inOutParam->currMBNum = VDC_MAX(inOutParam->currMBNum-1,startMB);
+
+      
+      inOutParam->currMBNum = lastMBNumInVP;
+   }
+
+   exitFunction:
+
+
+   exitWhenVOPHeaderCorrupted:
+
+   if (!fSegmentCorrupted) {
+      SOH_DEALLOC(pDiffMB);
+      return DGOB_OK;
+   }
+   else {
+      SOH_DEALLOC(pDiffMB);
+      return DGOB_OK_BUT_BIT_ERROR;
+   }
+
+   headerFailure:
+      SOH_DEALLOC(pDiffMB);
+      sncRewindAndSeekNewMPEGSync(-1, inBuffer, 0, &error);
+      if (error && error != ERR_BIB_NOT_ENOUGH_DATA)
+         return DGOB_ERR;
+      return DGOB_OK_BUT_BIT_ERROR;
+
+   unexpectedError:
+      SOH_DEALLOC(pDiffMB);
+      return DGOB_ERR;
+}
+// End of File