videoeditorengine/h263decoder/src/decgob.cpp
changeset 0 951a5db380a0
equal deleted inserted replaced
-1:000000000000 0:951a5db380a0
       
     1 /*
       
     2 * Copyright (c) 2010 Ixonos Plc.
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - Initial contribution
       
    11 *
       
    12 * Contributors:
       
    13 * Ixonos Plc
       
    14 *
       
    15 * Description:  
       
    16 * GOB decoding functions.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 /* 
       
    22  * Includes 
       
    23  */
       
    24 #include "h263dConfig.h"
       
    25 #include "decgob.h"
       
    26 #include "block.h"
       
    27 #include "debug.h"
       
    28 #include "decmbs.h"
       
    29 #include "stckheap.h"
       
    30 #include "sync.h"
       
    31 #include "viddemux.h"
       
    32 #include "biblin.h"
       
    33 /* MVE */
       
    34 #include "MPEG4Transcoder.h"
       
    35 
       
    36 
       
    37 /*
       
    38  * Global functions
       
    39  */
       
    40 
       
    41 /* {{-output"dgobGetAndDecodeGOBSegment.txt"}} */
       
    42 /*
       
    43  * dgobGetAndDecodeGOBSegment
       
    44  *    
       
    45  *
       
    46  * Parameters:
       
    47  *    inParam                    input parameters
       
    48  *    inOutParam                 input/output parameters, these parameters
       
    49  *                               may be modified in the function
       
    50  *
       
    51  * Function:
       
    52  *    This function gets and decodes a GOB segment which should start
       
    53  *    with a GBSC at the current position of the bit buffer.
       
    54  *
       
    55  * Returns:
       
    56  *    >= 0                       the function was successful
       
    57  *    < 0                        an error occured
       
    58  *
       
    59  */
       
    60 
       
    61 int dgobGetAndDecodeGOBSegment(
       
    62    const dgobGOBSegmentInParam_t *inParam,
       
    63    dgobGOBSegmentInOutParam_t *inOutParam,
       
    64    CMPEG4Transcoder *hTranscoder)
       
    65 /* {{-output"dgobGetAndDecodeGOBSegment.txt"}} */
       
    66 {
       
    67    bibBuffer_t 
       
    68       *inBuffer;        /* Input bit buffer instance */
       
    69 
       
    70    int 
       
    71       retValue,         /* Value returned from this function */
       
    72       
       
    73       fGetNewReferenceFrame,
       
    74                         /* 1 if the reference picture has changed from
       
    75                            the previous one */
       
    76       
       
    77       bitErrorIndication = 0, 
       
    78                         /* Carries bit error indication information returned
       
    79                            by the video demultiplexer module */
       
    80       
       
    81       intraGobsMissing = 0;
       
    82                         /* Flag to indicate if INTRA coded GOBs are missing */
       
    83       
       
    84    u_int32
       
    85       segmStart = bibNumberOfFlushedBits( inParam->inBuffer );
       
    86                         /* Start bit buffer position of the GOB segment */
       
    87 
       
    88    vdxGetGOBHeaderInputParam_t 
       
    89       vdxParam;         /* Input parameters for vdxGetGOBHeader */
       
    90 
       
    91    vdxGOBHeader_t 
       
    92       header;           /* GOB header data */
       
    93 
       
    94    inBuffer = inParam->inBuffer;
       
    95 
       
    96    /* 
       
    97     * Get GOB header 
       
    98     */
       
    99 
       
   100    vdxParam.numStuffBits = inParam->numStuffBits;
       
   101    vdxParam.fCustomPCF = inParam->pictParam->fCustomPCF;
       
   102    vdxParam.fCPM = inParam->pictParam->cpm;
       
   103    vdxParam.fRPS = inParam->pictParam->fRPS;
       
   104 
       
   105    if (vdxGetGOBHeader(inBuffer, &vdxParam, &header, &bitErrorIndication, 
       
   106        inParam->iColorEffect, &inOutParam->StartByteIndex, &inOutParam->StartBitIndex, hTranscoder) < 0) {
       
   107 
       
   108       deb("dgobGetAndDecodeGOBSegment: ERROR - vdxGetGOBHeader failed.\n");
       
   109       goto unexpectedError;
       
   110    }
       
   111 
       
   112    /*
       
   113     * Check header validity
       
   114     */
       
   115 
       
   116    if (header.gn >= inParam->pictParam->numGOBs) {
       
   117       deb("dgobGetAndDecodeGOBSegment: ERROR - too big GN.\n");
       
   118       goto unexpectedError;
       
   119    }
       
   120 
       
   121    /* If TRP present and TRP is not 8-bit if only 8-bit TRs have existed.
       
   122       Note: The following condition assumes that only 8-bit TRs are allowed. */
       
   123    if (header.trpi && header.trp > 255) {
       
   124       deb("dgobGetAndDecodeGOBSegment: ERROR - too big TRP.\n");
       
   125       goto unexpectedError;
       
   126    }
       
   127 
       
   128    /* If GFID is not as expected */
       
   129    if (inOutParam->gfid >= 0 && bitErrorIndication != 0 && 
       
   130       ((inParam->fGFIDShouldChange && inOutParam->gfid == header.gfid) ||
       
   131       (!inParam->fGFIDShouldChange && inOutParam->gfid != header.gfid))) {
       
   132       deb("dgobGetAndDecodeGOBSegment: ERROR - illegal GFID.\n");
       
   133       goto unexpectedError;
       
   134    }
       
   135 
       
   136    inOutParam->prevGN = inOutParam->prevGNWithHeader = header.gn;
       
   137    /* GFID was valid, and in the next GOB the gfidShouldChange flag should be 0 and GFID should be
       
   138       the same as the current one */
       
   139    inOutParam->gfid = header.gfid;
       
   140 
       
   141    fGetNewReferenceFrame = 0;
       
   142    if (inParam->pictParam->fRPS) {
       
   143       /* If TRP has changed */
       
   144       if ((header.trpi && header.trp != inOutParam->trp) ||
       
   145          (!header.trpi && inOutParam->trp >= 0))
       
   146          fGetNewReferenceFrame = 1;
       
   147 
       
   148       if (header.trpi)
       
   149          inOutParam->trp = header.trp;
       
   150       else
       
   151          inOutParam->trp = -1;
       
   152    }
       
   153 
       
   154   /* MVE */
       
   155      hTranscoder->H263GOBSliceHeaderEnded(&header, NULL);
       
   156    
       
   157 
       
   158    /*
       
   159     * Decode GOB contents
       
   160     */
       
   161 
       
   162    retValue = dgobGetAndDecodeGOBSegmentContents(inParam, fGetNewReferenceFrame, 
       
   163       header.gquant, inOutParam, hTranscoder);
       
   164 
       
   165   /* MVE */
       
   166     hTranscoder->H263OneGOBSliceWithHeaderEnded();
       
   167 
       
   168 
       
   169    if ( intraGobsMissing && retValue == 0 )
       
   170       return DGOB_OK_BUT_BIT_ERROR;
       
   171    else
       
   172       return retValue;
       
   173 
       
   174    unexpectedError:
       
   175       return DGOB_ERR;
       
   176 }
       
   177 
       
   178 
       
   179 /* {{-output"dgobGetAndDecodeGOBSegmentContents.txt"}} */
       
   180 /*
       
   181  * dgobGetAndDecodeGOBSegmentContents
       
   182  *    
       
   183  *
       
   184  * Parameters:
       
   185  *    inParam                    input parameters
       
   186  *    fGetNewReferenceFrame      non-zero if a new reference frame must be
       
   187  *                               requested from the image store, otherwise 0
       
   188  *    quant                      initial quantization parameter
       
   189  *    inOutParam                 input/output parameters, these parameters
       
   190  *                               may be modified in the function
       
   191  *
       
   192  * Function:
       
   193  *    This function gets and decodes the contents of a GOB segment
       
   194  *    meaning that the header of the GOB (either GOB header or picture
       
   195  *    header) is already got and processed and the macroblocks belonging
       
   196  *    to the GOB segment are decoded.
       
   197  *
       
   198  * Returns:
       
   199  *    >= 0                       the function was successful
       
   200  *    < 0                        an error occured
       
   201  *
       
   202  */
       
   203 
       
   204 int dgobGetAndDecodeGOBSegmentContents(
       
   205    const dgobGOBSegmentInParam_t *inParam,
       
   206    int fGetNewReferenceFrame,
       
   207    int quant,
       
   208    dgobGOBSegmentInOutParam_t *inOutParam,
       
   209    CMPEG4Transcoder *hTranscoder)
       
   210 /* {{-output"dgobGetAndDecodeGOBSegmentContents.txt"}} */
       
   211 {
       
   212    bibBuffer_t 
       
   213       *inBuffer;        /* Input bit buffer instance */
       
   214 
       
   215 
       
   216    bibBuffer_t 
       
   217        *outBuffer;        /* Output bit buffer instance */
       
   218    
       
   219    bibBufferEdit_t              
       
   220        *bufEdit; 
       
   221    
       
   222    int colorEffect; 
       
   223    TBool getDecodedFrame;
       
   224 
       
   225 
       
   226    /* decmbs input and output parameters */
       
   227    dmbPFrameMBInParam_t dpmbi;
       
   228    dmbPFrameMBInOutParam_t dpmbio;
       
   229    dmbIFrameMBInParam_t dimbi;
       
   230    dmbIFrameMBInOutParam_t dimbio;
       
   231 
       
   232    int 
       
   233       *pYPosInMBs,      /* Pointer to variable containing the y-position
       
   234                            of the current macroblock in macroblocks
       
   235                            (starting from zero in the top row) */
       
   236       fSegmentCorrupted = 0;
       
   237                         /* Flag to indicate if the current GOB segment
       
   238                            is corrupted */
       
   239 
       
   240    int16 
       
   241       error = 0;        /* Used to pass error codes from snc and erd modules */
       
   242 
       
   243    /* Pointers to pointers pointing to the top-left corner of the current 
       
   244       GOB (inside the current frame) */
       
   245    u_char **pYGOB, **pUGOB, **pVGOB;
       
   246 
       
   247    SOH_DEFINE(blcDiffMB_t, pDiffMB);
       
   248                         /* Storage for the previous difference blocks */
       
   249 
       
   250    inBuffer = inParam->inBuffer;
       
   251 
       
   252    outBuffer = inParam->outBuffer;
       
   253    bufEdit = inParam->bufEdit;
       
   254    colorEffect = inParam->iColorEffect;
       
   255    getDecodedFrame = inParam->iGetDecodedFrame;
       
   256 
       
   257 
       
   258    SOH_ALLOC(blcDiffMB_t, pDiffMB);
       
   259 
       
   260    if (pDiffMB == NULL) {
       
   261       deb("dgobGetAndDecodeGOBSegmentContents: SOH_ALLOC failed.\n");
       
   262       goto unexpectedError;
       
   263    }
       
   264 
       
   265    pDiffMB->cbpy = 0;
       
   266 
       
   267    /* If the reference frame changed */
       
   268    if (fGetNewReferenceFrame) {
       
   269       vdeIms_t *store = inOutParam->imageStore;
       
   270       vdeImsItem_t *imsItem;
       
   271       vdeImb_t *imb;
       
   272       int width, height;
       
   273 
       
   274       /* Get the reference frame */
       
   275       if (inOutParam->trp >= 0) {
       
   276          if (vdeImsGetReference(store, VDEIMS_REF_TR, inOutParam->trp, &imsItem) < 0) {
       
   277             deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImsGetReference "
       
   278                "failed.\n");
       
   279             goto unexpectedError;
       
   280          }
       
   281       }
       
   282 
       
   283       else {
       
   284          if (vdeImsGetReference(store, VDEIMS_REF_LATEST, 0, &imsItem) < 0) {
       
   285             deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImsGetReference "
       
   286                "failed.\n");
       
   287             goto unexpectedError;
       
   288          }
       
   289       }
       
   290 
       
   291       /* If no reference frame available */
       
   292       if (!imsItem) {
       
   293 
       
   294          /* Treat the situation like a decoding error.
       
   295             This should cause error concealment and
       
   296             a NACK message if Annex N is used. */
       
   297          deb("dgobGetAndDecodeGOBSegment: Warning - no reference frame "
       
   298             "available.\n");
       
   299 
       
   300          goto unexpectedError;
       
   301       }
       
   302 
       
   303       if (vdeImsStoreItemToImageBuffer(imsItem, &imb) < 0) {
       
   304          deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImsStoreItemToImageBuffer "
       
   305             "failed.\n");
       
   306          goto unexpectedError;
       
   307       }
       
   308 
       
   309       inOutParam->rtr = imb->tr;
       
   310 
       
   311       if (vdeImbYUV(imb, &inOutParam->refY, &inOutParam->refU, 
       
   312          &inOutParam->refV, &width, &height) < 0) {
       
   313          deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImbYUV "
       
   314             "failed.\n");
       
   315          goto unexpectedError;
       
   316       }
       
   317    }
       
   318 
       
   319    /* Preset structures for multiple macroblock decoding */
       
   320    if (inParam->pictParam->pictureType == VDX_PIC_TYPE_I) {
       
   321       dimbi.inBuffer = inBuffer;
       
   322 
       
   323 
       
   324       dimbi.outBuffer = outBuffer;
       
   325       dimbi.bufEdit = bufEdit;
       
   326       dimbi.iColorEffect = colorEffect; 
       
   327       dimbi.iGetDecodedFrame = getDecodedFrame; 
       
   328       dimbio.StartByteIndex = inOutParam->StartByteIndex;
       
   329       dimbio.StartBitIndex = inOutParam->StartBitIndex;
       
   330 
       
   331 
       
   332       dimbi.xPosInMBs = 0;
       
   333       /* yPosInMBs set inside the loop (below) */
       
   334       dimbi.pictParam = inParam->pictParam;
       
   335       dimbi.fGOBHeaderPresent = 1;
       
   336 
       
   337       dimbio.fCodedMBs = inOutParam->fCodedMBs;
       
   338       dimbio.numOfCodedMBs = inOutParam->numOfCodedMBs;
       
   339       dimbio.quant = quant;
       
   340 
       
   341       /* YUV pointers set iside the loop (below) */
       
   342 
       
   343       pYPosInMBs = &dimbi.yPosInMBs;
       
   344       pYGOB = &dimbio.yMBInFrame;
       
   345       pUGOB = &dimbio.uBlockInFrame;
       
   346       pVGOB = &dimbio.vBlockInFrame;
       
   347    }
       
   348 
       
   349    else {
       
   350       dpmbi.inBuffer = inBuffer;
       
   351 
       
   352       
       
   353       dpmbi.outBuffer = outBuffer;
       
   354       dpmbi.bufEdit = bufEdit;
       
   355       dpmbi.iColorEffect = colorEffect; 
       
   356       dpmbi.iGetDecodedFrame = getDecodedFrame;
       
   357       dpmbio.StartByteIndex = inOutParam->StartByteIndex;
       
   358       dpmbio.StartBitIndex = inOutParam->StartBitIndex;
       
   359 
       
   360 
       
   361       dpmbi.xPosInMBs = 0;
       
   362       /* yPosInMBs set inside the loop (below) */
       
   363       dpmbi.pictParam = inParam->pictParam;
       
   364       dpmbi.fGOBHeaderPresent = 1;
       
   365       dpmbi.refY = inOutParam->refY;
       
   366       dpmbi.refU = inOutParam->refU;
       
   367       dpmbi.refV = inOutParam->refV;
       
   368       dpmbi.currPY = inOutParam->currPY;
       
   369       dpmbi.currPU = inOutParam->currPU;
       
   370       dpmbi.currPV = inOutParam->currPV;
       
   371 
       
   372       dpmbio.fCodedMBs = inOutParam->fCodedMBs;
       
   373       dpmbio.numOfCodedMBs = inOutParam->numOfCodedMBs;
       
   374       dpmbio.quant = quant;
       
   375 
       
   376       /* YUV pointers set iside the loop (below) */
       
   377       dpmbio.mvcData = inOutParam->mvcData;
       
   378       dpmbio.diffMB = pDiffMB;
       
   379 
       
   380       pYPosInMBs = &dpmbi.yPosInMBs;
       
   381       pYGOB = &dpmbio.yMBInFrame;
       
   382       pUGOB = &dpmbio.uBlockInFrame;
       
   383       pVGOB = &dpmbio.vBlockInFrame;
       
   384    }
       
   385 
       
   386    /* Loop forever (until the GOB segment ends) */
       
   387    for (;;) {
       
   388       int dmbsRetValue;
       
   389       int numMBsInCurrGOB;
       
   390       int sncCode;
       
   391       int numStuffBits;
       
   392       int mbNumberInScanOrder;
       
   393 
       
   394       if ((inOutParam->prevGN == inParam->pictParam->numGOBs - 1) && 
       
   395          (inParam->pictParam->fLastGOBSizeDifferent))
       
   396          numMBsInCurrGOB = inParam->pictParam->numMBsInLastGOB;
       
   397       else
       
   398          numMBsInCurrGOB = inParam->pictParam->numMBsInGOB;
       
   399 
       
   400       *pYPosInMBs = inOutParam->prevGN * inParam->pictParam->numMBLinesInGOB;
       
   401 
       
   402       mbNumberInScanOrder = *pYPosInMBs * inParam->pictParam->numMBsInMBLine;
       
   403       
       
   404       /* Set pointers for the GOB (inside frame(s)) */
       
   405       if ( inOutParam->currPY != NULL )
       
   406       {
       
   407          int32 yOffset, uvOffset;
       
   408 
       
   409          yOffset = *pYPosInMBs * 16 * inParam->pictParam->lumMemWidth;
       
   410             
       
   411          *pYGOB = inOutParam->currPY + yOffset;
       
   412 
       
   413          uvOffset = yOffset / 4;
       
   414          *pUGOB = inOutParam->currPU + uvOffset;
       
   415          *pVGOB = inOutParam->currPV + uvOffset;
       
   416 
       
   417       }
       
   418       else
       
   419         {
       
   420         *pYGOB = NULL;
       
   421         *pUGOB = NULL;
       
   422         *pVGOB = NULL;
       
   423         }
       
   424 
       
   425       /* Decode macroblocks of the current GOB */
       
   426       if (inParam->pictParam->pictureType == VDX_PIC_TYPE_I)   {
       
   427          dimbi.numMBsInSegment = numMBsInCurrGOB;
       
   428          dmbsRetValue = dmbsGetAndDecodeIMBsInScanOrder(&dimbi, 
       
   429             &dimbio, &inOutParam->quantParams[mbNumberInScanOrder], hTranscoder);
       
   430          
       
   431          inOutParam->StartByteIndex = dimbio.StartByteIndex;
       
   432          inOutParam->StartBitIndex  = dimbio.StartBitIndex;
       
   433 
       
   434 
       
   435       }
       
   436       else  {
       
   437          dpmbi.numMBsInSegment = numMBsInCurrGOB;
       
   438          dmbsRetValue = dmbsGetAndDecodePMBsInScanOrder(&dpmbi,
       
   439             &dpmbio, &inOutParam->quantParams[mbNumberInScanOrder], hTranscoder);
       
   440          
       
   441          inOutParam->StartByteIndex = dpmbio.StartByteIndex;
       
   442          inOutParam->StartBitIndex  = dpmbio.StartBitIndex;
       
   443       }
       
   444 
       
   445       if (dmbsRetValue < 0)
       
   446          goto unexpectedError;
       
   447 
       
   448       /* Some bit errors were found inside the segment 
       
   449          (dpmbi/dimbi fSegmentCorrupted have the same address as fSegmentCorrupted)
       
   450          Note that if no suspicious/corrupted blocks was found, but there was crc-error, 
       
   451          this flag is not set. However, that case will be checked if no sync code is found */
       
   452       if ( fSegmentCorrupted )
       
   453          break;
       
   454 
       
   455       /* Check if there is a synchronization code in the current bitstream
       
   456          position */
       
   457       sncCode = sncCheckSync(inBuffer, &numStuffBits, &error);
       
   458 
       
   459       /* If buffer ends (in one-frame-per-one-buffer case) */
       
   460       if (error == ERR_BIB_NOT_ENOUGH_DATA)
       
   461          break;
       
   462 
       
   463       if (error)
       
   464          goto unexpectedError;
       
   465 
       
   466       /* If there is a synchronization code */
       
   467       if (sncCode != SNC_NO_SYNC )
       
   468          break;
       
   469 
       
   470 
       
   471       if (inOutParam->prevGN + 1 < inParam->pictParam->numGOBs) 
       
   472          inOutParam->prevGN++;
       
   473 
       
   474       else {
       
   475          deb("dgobGetAndDecodeGOBSegment: ERROR - too much frame data.\n");
       
   476          fSegmentCorrupted = 1;
       
   477          break;
       
   478       }
       
   479 
       
   480       dpmbi.fGOBHeaderPresent = 0;
       
   481       dimbi.fGOBHeaderPresent = 0;
       
   482    }
       
   483 
       
   484    /* Update coded macroblock counter */
       
   485    if (inParam->pictParam->pictureType == VDX_PIC_TYPE_I)
       
   486       inOutParam->numOfCodedMBs = dimbio.numOfCodedMBs;
       
   487    else
       
   488       inOutParam->numOfCodedMBs = dpmbio.numOfCodedMBs;
       
   489 
       
   490    if (!fSegmentCorrupted) {
       
   491       SOH_DEALLOC(pDiffMB);
       
   492       if (inOutParam->trp >= 0) {
       
   493       }
       
   494 
       
   495       return DGOB_OK;
       
   496    }
       
   497    else {
       
   498 
       
   499       return DGOB_OK_BUT_BIT_ERROR;
       
   500    }
       
   501 
       
   502    unexpectedError:
       
   503       SOH_DEALLOC(pDiffMB);
       
   504       return DGOB_ERR;
       
   505 }
       
   506 
       
   507 
       
   508 // End of File