--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/h263decoder/src/core_mpeg.cpp Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,671 @@
+/*
+* 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:
+* MPEG-4 decoder core functions.
+*
+*/
+
+
+/*
+ * Includes
+ */
+#include "h263dConfig.h"
+#include "vdc263.h"
+#include "core.h"
+#include "debug.h"
+#include "decblock.h" /* for dblFree and dblLoad */
+#include "decvp_mpeg.h"
+#include "decpich.h"
+#include "h263dapi.h" /* for H263D_BC_MUX_MODE_SEPARATE_CHANNEL and H263D_ERD_ */
+#include "stckheap.h"
+#include "sync.h"
+#include "vdeims.h"
+#include "vdeimb.h"
+#include "viddemux.h"
+#include "biblin.h"
+/* MVE */
+#include "MPEG4Transcoder.h"
+
+
+/*
+ * Typedefs and structs
+ */
+
+/* This structure is used to indicate the expected decoding position. */
+typedef enum {
+ EDP_START_OF_FRAME,
+ EDP_START_OF_VIDEO_PACKET,
+ EDP_END_OF_FRAME
+} vdcExpectedDecodingPosition_t;
+
+
+/*
+ * Local function prototypes
+ */
+
+extern int vdcFillImageBuffers(
+ vdcInstance_t *instance,
+ int numOfCodedMBs,
+ vdeImb_t *imbP);
+
+
+/*
+ * Global functions
+ */
+
+/* {{-output"vdcDecodeMPEGVolHeader.txt"}} */
+/*
+ * vdcDecodeMPEGVolHeader
+ *
+ *
+ * Parameters:
+ * None.
+ *
+ * Function:
+ * This function reads the VOL Header and updates the instance data
+ * with the read parameters.
+ *
+ * Returns:
+ * >= 0 if succeeded
+ * < 0 if failed
+ *
+ */
+
+int vdcDecodeMPEGVolHeader(vdcHInstance_t hInstance, bibBuffer_t *inBuffer, CMPEG4Transcoder *hTranscoder)
+/* {{-output"vdcDecodeMPEGVolHeader.txt"}} */
+{
+ dphInOutParam_t pichInOut;
+ int headerSuccess = 0;
+
+ pichInOut.vdcInstance = (vdcInstance_t *) hInstance;
+ pichInOut.inBuffer = inBuffer;
+
+ headerSuccess = dphGetMPEGVolHeader(&pichInOut, hTranscoder);
+ if (headerSuccess != 0)
+ return VDC_ERR;
+ else
+ return VDC_OK;
+}
+
+
+/* {{-output"vdcDecodeMPEGVop.txt"}} */
+/*
+ * vdcDecodeMPEGVop
+ *
+ *
+ * Parameters:
+ * hInstance handle of instance data
+ *
+ * inBuffer pointer to bit buffer, the current position
+ * of the buffer must start with a PSC
+ *
+ * Function:
+ * The vdcDecodeMPEGVop function implements the decoding process of the MPEG-4
+ * Simple Video Object described in ISO/IEC 14496-2.
+ *
+ * The function decodes the next frame in the buffer (inBuffer) meaning that
+ * the decoding continues until the next VOP start code or EOB is found or
+ * until the end of the buffer is not reached.
+ *
+ * Returns:
+ * VDC_OK if the function was succesful
+ * VDC_OK_BUT_BIT_ERROR if bit errors were detected but
+ * decoded frames are provided by concealing
+ * the errors
+ * VDC_OK_BUT_FRAME_USELESS if severe bit errors were detected
+ * (no concealment was possible) or
+ * the bitstream ended unexpectedly
+ * VDC_ERR if a processing error occured,
+ * the instance should be closed
+ *
+ */
+int vdcDecodeMPEGVop(vdcHInstance_t hInstance, bibBuffer_t *inBuffer, bibBuffer_t *outBuffer,
+ bibBufferEdit_t *bufEdit, int aColorEffect, TBool aGetDecodedFrame,
+ int aStartByteIndex, int aStartBitIndex,
+ CMPEG4Transcoder *hTranscoder)
+/* {{-output"vdcDecodeMPEGVop.txt"}} */
+{
+ int sncCode; /* the latest synchronization code, see
+ sncCheckSync for the possible values */
+
+ int retValue = VDC_OK; /* return value of this function */
+
+ int16 error = 0;
+
+ u_char
+ *currYFrame = NULL, /* current P frame */
+ *currUFrame = NULL,
+ *currVFrame = NULL,
+ *refYFrame = NULL, /* reference frame */
+ *refUFrame = NULL,
+ *refVFrame = NULL;
+
+ u_char *fCodedMBs = NULL; /* Pointer to table, which indicates coded \
+ macroblocks by non-zero value */
+ int numOfCodedMBs = 0; /* The number of coded macroblocks */
+
+ int *quantParams = NULL; /* Pointer to table, in which the quantization
+ parameter for each macroblock is stored */
+
+ int currMBNum = 0; /* Current macro block */
+
+ int decStatus = 0;
+ int corruptedVPs = 0;
+ int numberOfVPs = 1;
+ int headerSuccess = 0;
+ u_char fVOPHeaderCorrupted = 0, fVOPHeaderLost = 0;
+
+ vdcExpectedDecodingPosition_t expectedDecodingPosition;
+ /* Tells in which part of the bitstream
+ the decoding should be */
+
+ vdcInstance_t *instance = (vdcInstance_t *) hInstance;
+ /* instance data */
+
+ vdcAssert(instance != NULL);
+
+ /* Initializations */
+
+ instance->currFrame = NULL;
+ expectedDecodingPosition = EDP_START_OF_FRAME;
+
+ /* Main loop */
+ for (;;) {
+ int bitErrorIndication = 0;
+
+ sncCode = sncCheckMpegSync(inBuffer, instance->pictureParam.fcode_forward, &error);
+
+ /* If sncCheckSync failed */
+ if (error && error != ERR_BIB_NOT_ENOUGH_DATA) {
+ deb1p("vdcDecodeMPEGVop: ERROR - sncCheckSync returned %d.\n", error);
+ retValue = VDC_ERR;
+ goto exitFunction;
+ }
+
+ /* If EOS was got */
+ if (sncCode == SNC_EOB)
+ instance->fEOS = 1;
+
+ /* If frame ends appropriately */
+ if (expectedDecodingPosition == EDP_END_OF_FRAME &&
+ (sncCode == SNC_VOP || sncCode == SNC_GOV || sncCode == SNC_EOB ||
+ sncCode == SNC_STUFFING || error == ERR_BIB_NOT_ENOUGH_DATA))
+ goto exitFunction;
+
+ /* Else if frame (or stream) data ends suddenly */
+ else if (error == ERR_BIB_NOT_ENOUGH_DATA) {
+ retValue = VDC_OK_BUT_BIT_ERROR;
+ goto exitFunction;
+ }
+
+ /* Else if EOS was reached */
+ else if (sncCode == SNC_EOB) {
+ /* The current frame is useless since it ends before it is complete.
+ On the other hand, there is no point in concealing it since
+ it is the last frame of the sequence. */
+ goto exitFunction;
+ }
+
+ /* Else if frame starts as expected */
+ else if (expectedDecodingPosition == EDP_START_OF_FRAME &&
+ ((sncCode == SNC_GOV) || (sncCode == SNC_VOP) || fVOPHeaderLost)) {
+
+ dphInParam_t pichIn;
+ dphInOutParam_t pichInOut;
+ dphOutParam_t pichOut;
+
+ if (sncCode == SNC_GOV) {
+ vdxGovHeader_t govHeader;
+
+ headerSuccess = vdxGetGovHeader(inBuffer, &govHeader, &bitErrorIndication);
+ if ( headerSuccess < 0) {
+ retValue = VDC_ERR;
+ goto exitFunction;
+ } else if (( headerSuccess > 0 ) ||
+ (govHeader.time_stamp < instance->pictureParam.mod_time_base) ||
+ (govHeader.time_stamp - instance->pictureParam.mod_time_base > 60)) {
+
+ if(sncCheckMpegVOP(inBuffer, &error) != SNC_PSC) {
+ retValue = VDC_OK_BUT_FRAME_USELESS;
+ goto exitFunction;
+ }
+
+ } else {
+ instance->pictureParam.mod_time_base = govHeader.time_stamp;
+
+ /* copying the user data */
+ if (govHeader.user_data != NULL) {
+
+ if (!instance->user_data)
+ instance->user_data = (char *) vdcMalloc(
+ MAX_USER_DATA_LENGTH);
+
+ govHeader.user_data_length =
+ ((instance->user_data_length + govHeader.user_data_length) >= MAX_USER_DATA_LENGTH) ?
+ (MAX_USER_DATA_LENGTH - instance->user_data_length) : govHeader.user_data_length;
+ memcpy(
+ instance->user_data + instance->user_data_length,
+ govHeader.user_data,
+ govHeader.user_data_length);
+ instance->user_data_length += govHeader.user_data_length;
+
+ vdcDealloc(govHeader.user_data);
+ }
+
+ }
+ }
+
+ /* Start VOP decoding */
+ pichIn.fReadBits = (fVOPHeaderLost ? 0 : 1);
+ pichIn.fNeedDecodedFrame = aGetDecodedFrame | hTranscoder->NeedDecodedYUVFrame();
+ pichInOut.vdcInstance = instance;
+ pichInOut.inBuffer = inBuffer;
+
+ /* Get VOP header */
+ headerSuccess = dphGetMPEGVopHeader(&pichIn, &pichInOut, &pichOut, &bitErrorIndication);
+
+ deb1p("vdcDecodeMPEGVop: frameNum %d.\n", instance->frameNum);
+ if ( headerSuccess < 0) {
+ retValue = VDC_ERR;
+ goto exitFunction;
+ } else if ( headerSuccess > 0 ) {
+
+ if (headerSuccess == DPH_OK_BUT_BIT_ERROR) {
+ /* find the next resync marker, to get the number of MBs in the current VP */
+ sncCode = sncRewindAndSeekNewMPEGSync(-1, inBuffer, instance->pictureParam.fcode_forward, &error);
+ if (error && error != ERR_BIB_NOT_ENOUGH_DATA) {
+ retValue = VDC_ERR;
+ goto exitFunction;
+ }
+
+ if (sncCode == SNC_VIDPACK) {
+ fVOPHeaderCorrupted = 1;
+ } else {
+ retValue = VDC_OK_BUT_FRAME_USELESS;
+ goto exitFunction;
+ }
+
+ } else if (headerSuccess == DPH_OK_BUT_NOT_CODED) {
+
+ /* MVE */
+ /* copy VOP header to output buffer in case VOP is not coded, including the GOV */
+ bufEdit->copyMode = CopyWhole; /* copyWhole */
+ CopyStream(inBuffer,outBuffer,bufEdit, aStartByteIndex, aStartBitIndex);
+
+ /* behaves the same as if the frame was useless, but it's just not coded */
+ retValue = VDC_OK_BUT_NOT_CODED;
+ goto exitFunction;
+ }
+ }
+
+
+ currYFrame = pichOut.currYFrame;
+ currUFrame = pichOut.currUFrame;
+ currVFrame = pichOut.currVFrame;
+
+ currMBNum = 0;
+
+ numOfCodedMBs = 0;
+ fCodedMBs = renDriCodedMBs(instance->currFrame->imb->drawItem);
+ memset(fCodedMBs, 0, renDriNumOfMBs(
+ instance->currFrame->imb->drawItem) * sizeof(u_char));
+
+ /* Initialize quantization parameter array */
+ quantParams = instance->currFrame->imb->yQuantParams;
+ memset(quantParams, 0, renDriNumOfMBs(
+ instance->currFrame->imb->drawItem) * sizeof(int));
+
+ /* If this is the first frame and callback function has been set, report frame size */
+ if (instance->nOfDecodedFrames == 0 && instance->reportPictureSizeCallback) {
+ h263dReportPictureSizeCallback_t cb =
+ (h263dReportPictureSizeCallback_t)instance->reportPictureSizeCallback;
+ cb(instance->hParent, instance->pictureParam.lumWidth, instance->pictureParam.lumHeight);
+ }
+
+ /* Decode the 1st VP segment */
+ {
+ dvpVPInParam_t dvpi;
+ dvpVPInOutParam_t dvpio;
+
+ dvpi.pictParam = &instance->pictureParam;
+ dvpi.inBuffer = inBuffer;
+ dvpi.outBuffer = outBuffer;
+ dvpi.bufEdit = bufEdit;
+ dvpi.iColorEffect = aColorEffect;
+ dvpi.iGetDecodedFrame = aGetDecodedFrame;
+
+ if (fVOPHeaderLost) fVOPHeaderCorrupted = 1;
+ dvpi.fVOPHeaderCorrupted = fVOPHeaderCorrupted;
+
+ dvpio.currMBNum = 0;
+ dvpio.quant = pichOut.pquant;
+ dvpio.fCodedMBs = fCodedMBs;
+ dvpio.numOfCodedMBs = numOfCodedMBs;
+ dvpio.quantParams = quantParams;
+ dvpio.mvcData = &instance->mvcData;
+ dvpio.aicData = &instance->aicData;
+ dvpio.imageStore = instance->imageStore;
+ dvpio.frameNum = instance->frameNum;
+
+ dvpio.refY = refYFrame;
+ dvpio.refU = refUFrame;
+ dvpio.refV = refVFrame;
+ dvpio.currPY = currYFrame;
+ dvpio.currPU = currUFrame;
+ dvpio.currPV = currVFrame;
+
+ /* MVE */
+ hTranscoder->VOPHeaderEnded(aStartByteIndex, aStartBitIndex,
+ pichOut.pquant, instance->pictureParam.pictureType,
+ instance->frameNum, headerSuccess == DPH_OK_BUT_NOT_CODED);
+ /* VOP header parsing success, begin on VP */
+ hTranscoder->BeginOneVideoPacket(&dvpi);
+ hTranscoder->AfterVideoPacketHeader(&dvpio); // the first VP does not have VPHeader
+
+ decStatus = dvpGetAndDecodeVideoPacketContents(&dvpi,
+ instance->pictureParam.pictureType != VDX_PIC_TYPE_I,
+ &dvpio, hTranscoder);
+
+ if (decStatus < 0) {
+ retValue = VDC_ERR;
+ goto exitFunction;
+ } else if (decStatus > 0 ) {
+ if (decStatus == DGOB_OK_BUT_FRAME_USELESS) {
+ retValue = VDC_OK_BUT_FRAME_USELESS;
+ goto exitFunction;
+ }
+ corruptedVPs ++;
+ }
+
+ /* MVE */
+ /* the first VP ends */
+ hTranscoder->OneVPEnded();
+
+ currMBNum = dvpio.currMBNum;
+ numOfCodedMBs = dvpio.numOfCodedMBs;
+ refYFrame = dvpio.refY;
+ refUFrame = dvpio.refU;
+ refVFrame = dvpio.refV;
+
+
+ if ((decStatus == DGOB_OK && currMBNum == instance->pictureParam.numMBsInGOB) ||
+ (decStatus == DGOB_OK_BUT_BIT_ERROR && sncCheckMpegVOP(inBuffer, &error) == SNC_PSC))
+ expectedDecodingPosition = EDP_END_OF_FRAME;
+ else
+ expectedDecodingPosition = EDP_START_OF_VIDEO_PACKET;
+ }
+ }
+
+ /* Else if Video Packet starts as expected */
+ else if (expectedDecodingPosition == EDP_START_OF_VIDEO_PACKET &&
+ sncCode == SNC_VIDPACK) {
+
+ dvpVPInParam_t dvpi;
+ dvpVPInOutParam_t dvpio;
+
+ dvpi.pictParam = &instance->pictureParam;
+ dvpi.inBuffer = inBuffer;
+ dvpi.outBuffer = outBuffer;
+ dvpi.bufEdit = bufEdit;
+ dvpi.iColorEffect = aColorEffect;
+ dvpi.iGetDecodedFrame = aGetDecodedFrame;
+ dvpi.fVOPHeaderCorrupted = fVOPHeaderCorrupted;
+
+ dvpio.currMBNum = currMBNum;
+ dvpio.fCodedMBs = fCodedMBs;
+ dvpio.numOfCodedMBs = numOfCodedMBs;
+ dvpio.quantParams = quantParams;
+ dvpio.mvcData = &instance->mvcData;
+ dvpio.aicData = &instance->aicData;
+ dvpio.imageStore = instance->imageStore;
+
+ dvpio.refY = refYFrame;
+ dvpio.refU = refUFrame;
+ dvpio.refV = refVFrame;
+ dvpio.currPY = currYFrame;
+ dvpio.currPU = currUFrame;
+ dvpio.currPV = currVFrame;
+
+ /* MVE */
+ /* VOP header parsing success, begin on VP */
+ hTranscoder->BeginOneVideoPacket(&dvpi);
+
+ /* if the VOP header data needs to be corrected from the HEC codes set
+ inParam->fVOPHeaderCorrupted and pictParam values will be set + read
+ inOutParam->frameNum into instance->frameNum */
+ decStatus = dvpGetAndDecodeVideoPacketHeader(&dvpi, &dvpio);
+
+ /* MVE */
+ /* After parsing the VP header */
+ hTranscoder->AfterVideoPacketHeader(&dvpio);
+
+ if (decStatus < 0) {
+ retValue = VDC_ERR;
+ goto exitFunction;
+ } else if (decStatus > 0) {
+
+ if (fVOPHeaderCorrupted) {
+ /* this is also true when the whole packet with the VOP header is lost */
+
+ if (dvpio.frameNum <= instance->frameNum) {
+ /* VOP header could not be recovered from HEC (there was no HEC)
+ or there was an error in the VP header: in this case should we try to recover
+ VOP header from the next VP instead of the exiting here? */
+ retValue = VDC_OK_BUT_FRAME_USELESS;
+ goto exitFunction;
+
+ } else {
+ /* VOP header was succesfully recovered from HEC,
+ the first VP is treated as corrupted or lost */
+ instance->frameNum = dvpio.frameNum;
+
+ }
+ } else if (currMBNum < dvpio.currMBNum) {
+ /* when there was no bit-error in the VP header and the MB counter shows difference
+ we know, that a whole VP was lost */
+
+ corruptedVPs++;
+ numberOfVPs++;
+
+
+ }
+ }
+
+ numberOfVPs++;
+
+ if (!decStatus) {
+
+
+ decStatus = dvpGetAndDecodeVideoPacketContents(&dvpi,0,&dvpio, hTranscoder);
+ if (decStatus < 0) {
+ retValue = VDC_ERR;
+ goto exitFunction;
+ } else if (decStatus > 0 ) {
+ if (decStatus == DGOB_OK_BUT_FRAME_USELESS) {
+ retValue = VDC_OK_BUT_FRAME_USELESS;
+ goto exitFunction;
+ }
+ corruptedVPs++;
+ }
+
+ }
+
+ /* MVE */
+ hTranscoder->OneVPEnded();
+
+ currMBNum = dvpio.currMBNum;
+ numOfCodedMBs = dvpio.numOfCodedMBs;
+
+ if ((decStatus == DGOB_OK && currMBNum == instance->pictureParam.numMBsInGOB) ||
+ (decStatus == DGOB_OK_BUT_BIT_ERROR && sncCheckMpegVOP(inBuffer, &error) == SNC_PSC))
+ expectedDecodingPosition = EDP_END_OF_FRAME;
+ else {
+ expectedDecodingPosition = EDP_START_OF_VIDEO_PACKET;
+ if (fVOPHeaderCorrupted) fVOPHeaderCorrupted=0;
+ }
+ }
+
+ /* Else decoding is out of sync */
+ else {
+ switch (expectedDecodingPosition) {
+
+ case EDP_START_OF_FRAME:
+ if (sncCode == SNC_VIDPACK) {
+ /* VP start code instead of VOP start code ->
+ packet including VOP header is lost */
+ fVOPHeaderLost = 1;
+ continue;
+ } else {
+ /* No start code */
+ retValue = VDC_OK_BUT_FRAME_USELESS;
+ goto exitFunction;
+ }
+
+ case EDP_START_OF_VIDEO_PACKET:
+ /* If the decoding gets out of sync, the next sync code is
+ seeked in dvpGetAndDecodeVideoPacketContents. Then, if
+ the frame ends instead of a new VP header, we are here. */
+
+ /* Mark the missing VP corrupted */
+ {
+ numberOfVPs++;
+ corruptedVPs++;
+
+ }
+
+ retValue = VDC_OK_BUT_BIT_ERROR;
+ goto exitFunction;
+
+ case EDP_END_OF_FRAME:
+ /* Too much data */
+ retValue = VDC_OK_BUT_BIT_ERROR;
+ goto exitFunction;
+ }
+ }
+ }
+
+
+
+exitFunction:
+
+ /* MVE */
+ hTranscoder->VOPEnded();
+
+ if (sncCheckMpegSync(inBuffer, instance->pictureParam.fcode_forward, &error) == SNC_EOB) {
+ instance->fEOS = 1;
+ }
+
+ /* If frame(s) not useless */
+ if (retValue == VDC_OK || retValue == VDC_OK_BUT_BIT_ERROR) {
+
+ /* If bit errors */
+ if (corruptedVPs) {
+ retValue = VDC_OK_BUT_FRAME_USELESS;
+ }
+
+ if ( retValue != VDC_OK_BUT_FRAME_USELESS ) {
+
+ if ( instance->nOfDecodedFrames < 0xffffffff )
+ instance->nOfDecodedFrames++;
+ if (vdcFillImageBuffers(instance, numOfCodedMBs,
+ instance->currFrame->imb) < 0)
+ retValue = VDC_ERR;
+
+ }
+ }
+
+ /* If a fatal error occurred */
+ if (retValue < 0) {
+ /* Return frame buffers for decoded output images,
+ as they are useless for the caller and
+ as the caller cannot get a handle to return them */
+ if (instance->currFrame)
+ vdeImsPutFree(instance->imageStore, instance->currFrame);
+ }
+
+ return retValue;
+}
+
+
+/* {{-output"vdcIsMPEGINTRA.txt"}} */
+/*
+ * vdcIsMPEGINTRA
+ *
+ *
+ * Parameters:
+ * hInstance handle of instance data
+ * frameStart pointer to memory chunk containing a frame
+ * frameLength number of bytes in frame
+ *
+ * Function:
+ * This function returns 1 if the passed frame is an INTRA frame.
+ * Otherwise the function returns 0.
+ *
+ * Returns:
+ * See above.
+ *
+ *
+ */
+
+int vdcIsMPEGINTRA(
+ vdcHInstance_t hInstance,
+ void *frameStart,
+ unsigned frameLength)
+/* {{-output"vdcIsINTRA.txt"}} */
+{
+ bibBuffer_t *tmpBitBuffer;
+ int fINTRA = 0, bitErrorIndication, syncCode, vdxStatus;
+ int16 error = 0;
+ vdcInstance_t *instance = (vdcInstance_t *) hInstance;
+ vdxGovHeader_t govHeader;
+
+ vdcAssert(instance);
+
+ tmpBitBuffer = bibCreate(frameStart, frameLength, &error);
+ if (!tmpBitBuffer || error)
+ return 0;
+
+ syncCode = sncCheckMpegSync(tmpBitBuffer, instance->pictureParam.fcode_forward, &error);
+
+ if ((syncCode == SNC_GOV || syncCode == SNC_VOP) && error == 0) {
+ vdxGetVopHeaderInputParam_t vopIn;
+ vdxVopHeader_t vopOut;
+
+ if (syncCode == SNC_GOV) {
+ vdxStatus = vdxGetGovHeader(tmpBitBuffer, &govHeader,
+ &bitErrorIndication);
+
+ if (vdxStatus < 0 || bitErrorIndication != 0)
+ return fINTRA;
+ }
+
+ /* MVE */
+ int dummy1, dummy2, dummy3, dummy4; /* not used for any processing */
+ /* Get VOP header */
+ vopIn.time_increment_resolution = instance->pictureParam.time_increment_resolution;
+ vdxStatus = vdxGetVopHeader(tmpBitBuffer, &vopIn, &vopOut,
+ &dummy1, &dummy2, &dummy3, &dummy4,
+ &bitErrorIndication);
+
+
+ if (vdxStatus >= 0 && bitErrorIndication == 0)
+ fINTRA = (vopOut.coding_type == VDX_VOP_TYPE_I);
+ }
+
+ bibDelete(tmpBitBuffer, &error);
+
+ return fINTRA;
+}
+// End of File